加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 在宏中使用私有构造函数

发布时间:2020-12-16 09:34:31 所属栏目:安全 来源:网络整理
导读:我想在宏中使用一个私有的构造函数。此示例为正整数,但基本模式不仅可用于其他数字类型,如偶数,还可用于字符串派生类型,如电子邮件地址或目录名称。通过使构造函数为私有,用户被拒绝机会进??行非法类型。我有以下代码: object PosInt{ import language
我想在宏中使用一个私有的构造函数。此示例为正整数,但基本模式不仅可用于其他数字类型,如偶数,还可用于字符串派生类型,如电子邮件地址或目录名称。通过使构造函数为私有,用户被拒绝机会进??行非法类型。我有以下代码:

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构造函数是私有的,虽然Macro按预期编译,但如果尝试使用宏,则会收到错误。我无法手动构建表达式树,但我不知道这是否会有帮助。有没有办法我可以做到这一点?

即使PosInt不是值类,你仍然无法使用私有构造函数。我会接受一个不使用价值类的答案。值类的缺点是它们得到类型擦除。加上我对2d坐标的子集感兴趣的课程无法实现为价值类。我对实体整数并不感兴趣,我只是用它们作为一个简单的测试台。我正在使用Scala 2.11M5。 Scala 2.11将添加quasiquote功能。我还没有弄清楚如何使用quasiquotes,因为现在所有的材料似乎都熟悉了我没有的宏观乐园。

解决方法

不幸的是,为了实现这些目标,宏不能这样工作。他们只是在编译时操纵AST。无论最终的结果如何,它总是可以在Scala中写的(没有宏)。

因此,为了限制PosInt的可能值,您需要在公共构造函数或伴随对象的工厂方法中进行运行时检查。

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

>使构造函数在类上私有。
>提供(例如)返回Option [PosInt](或Try [PosInt])或其他类型的您可以在参数超出范围时表示“失败”的伴侣对象上的create方法。 。
>为您的示例提供一个适用对象的应用方法,该示例在编译时验证该参数在范围内,然后返回一个简单地调用create(x).get的表达式树。

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读