在宏中使用私有构造函数



我想在宏中使用私有构造函数。此示例是一个正整数,但基本模式不仅可以用于其他数字类型(如偶数(,还可以用于字符串派生类型(如电子邮件地址或目录名称(。通过将构造函数设为私有,用户将失去创建非法类型的机会。我有以下代码:

object PosInt
{
  import language.experimental.macros 
  import reflect.runtime.universe._
  import reflect.macros.Context
  def op(inp: Int): Option[PosInt] = if (inp > 0) Some(new PosInt(inp)) else None
  def apply(param: Int): PosInt = macro apply_impl
  def apply_impl(c: Context)(param: c.Expr[Int]): c.Expr[PosInt] =
  {
    import c.universe._
    param match {
      case Expr(Literal(i)) if (i.value.asInstanceOf[Int] > 0) =>
      case Expr(Literal(i)) if (i.value.asInstanceOf[Int] == 0) => c.abort(c.enclosingPosition, "0 is not a positive integer") 
      case Expr(Literal(i)) => c.abort(c.enclosingPosition, "is not a positive integer")      
      case _ => c.abort(c.enclosingPosition, "Not a Literal")
    }    
    reify{new PosInt(param.splice)}    
  }  
}
class PosInt (val value: Int) extends AnyVal

但是,如果我将 PosInt 构造函数设为私有,尽管宏按预期编译,但如果尝试使用该宏,我会收到错误。我无法弄清楚如何手动构建表达式树,但我不确定这是否有帮助。无论如何我能做到这一点吗?

即使 PosInt 不是值类,您仍然无法使用私有构造函数。 我将接受不使用值类的答案。值类的缺点是它们会擦除类型。另外,我感兴趣的类(如 2D 坐标的子集(无论如何都不能实现为值类。我实际上对正整数不感兴趣,我只是将它们用作简单的测试平台。我正在使用 Scala 2.11M5。Scala 2.11 将增加准引号功能。我还没有弄清楚如何使用准引号,因为目前它们的所有材料似乎都假设对宏观天堂很熟悉,而我没有。

不幸的是,对于您要实现的目标,宏无法以这种方式工作。他们只是在编译时操作 AST。无论最终结果是什么,它总是你可以用Scala(没有宏(从字面上写的东西。

因此,为了约束PosInt的可能值,您需要在某个地方进行运行时检查,无论是在公共构造函数中还是在配套对象的工厂方法中。

如果运行时异常不适合您,那么一种可能的方法是:

  • 使构造函数在类上私有。
  • 例如,在伴随对象上提供一个返回 Option[PosInt]create 方法(或 Try[PosInt] ,或您选择的某种其他类型的方法,允许您在参数超出范围时表示"失败"(。
  • 在配套对象上提供一个类似于示例的 apply 方法,该方法在编译时验证参数是否在范围内,然后返回一个仅调用 create(x).get 的表达式树。

在这种情况下,在选项上调用.get是可以接受的,因为您确定它永远不会None

缺点是您必须重复检查两次:一次在编译时,一次在运行时。

我不是专家,但我想我会试一试......在 Java 中,私有构造函数的作用域仅限于同一类......因此,需要将 PosInt 对象移动到调用它的同一类的作用域中。话虽如此,我找到了一篇文章,其中显示了两种可以防止对象被继承的方法@ http://www.developer.com/java/other/article.php/3109251/Stopping-Your-Class-from-Being-Inherited-in-Java-the-Official-Way-and-the-Unofficial-Way.htm

描述了在类声明中使用"final"关键字以防止它被继承。这是"官方"的方式。"非官方"的方法是使构造函数私有,但添加一个返回类对象的公共静态方法......

是的,我知道,这是一个老问题...但没有得到答复。你永远不知道什么时候一个老问题会成为某人搜索结果中最受欢迎的......

相关内容

  • 没有找到相关文章

最新更新