Ric*_*ver 17 macros scala private-constructor
我想在宏中使用私有构造函数.此示例是一个正整数,但基本模式不仅可以用于其他数字类型(如偶数),还可以用于字符串派生类型(如电子邮件地址或目录名称).通过使构造函数为私有,用户被拒绝制作非法类型的机会.我有以下代码:
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
Run Code Online (Sandbox Code Playgroud)
但是,如果我将PosInt构造函数设为私有,虽然宏按预期编译,但如果尝试使用宏,则会出错.我无法弄清楚如何手动构建表达式树,但我不确定这是否会有所帮助.无论如何我能做到吗?
即使PosInt不是值类,您仍然无法使用私有构造函数.我会接受一个不使用值类的答案.值类的缺点是它们得到类型擦除.我喜欢的类,如2d坐标的子集,无论如何都不能实现为值类.我实际上并不对正整数感兴趣,我只是将它们用作一个简单的试验台.我正在使用Scala 2.11M5.Scala 2.11将增加quasiquotes功能.我还没有弄清楚如何使用quasiquotes,因为目前它们上面的所有材料似乎都是对Macro Paradise的熟悉,我没有.
小智 0
我不是专家,但我想我会尝试一下...在 Java 中,私有构造函数的范围仅限于同一个类...因此 PosInt 对象需要移入范围与被调用的类属于同一类。话虽如此,我发现一篇文章展示了两种防止对象被继承的方法@ http://www.developer.com/java/other/article.php/3109251/Stopping-Your-Class-from-Being -Java中继承的官方方式和非官方方式.htm
它描述了在类声明中使用“final”关键字来防止它被继承。这就是“官方”方式。“非官方”方法是将构造函数设为私有,但添加一个返回类对象的公共静态方法......
是的,我知道,这是一个老问题......但它没有得到解答。你永远不知道什么时候一个老问题会成为某人搜索结果中的热门问题......