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

scala – 隐式参数解析 – 设置优先级

发布时间:2020-12-16 19:12:27 所属栏目:安全 来源:网络整理
导读:我正在尝试创建一个类型类Default,它提供给定类型的默认值.这是我到目前为止提出的: trait Default[A] { def value: A}object Default { def withValue[A](a: A) = new Default[A] { def value = a } def default[A : Default]: A = implicitly[Default[A]]
我正在尝试创建一个类型类Default,它提供给定类型的默认值.这是我到目前为止提出的:

trait Default[A] {
  def value: A
}

object Default {
  def withValue[A](a: A) = new Default[A] {
    def value = a
  }

  def default[A : Default]: A = implicitly[Default[A]].value

  implicit val forBoolean = withValue(false)

  implicit def forNumeric[A : Numeric] = 
    withValue(implicitly[Numeric[A]].zero)

  implicit val forChar = withValue(' ')

  implicit val forString = withValue("")

  implicit def forOption[A] = withValue(None : Option[A])

  implicit def forAnyRef[A >: Null] = withValue(null : A)
}

case class Person(name: String,age: Int)

case class Point(x: Double,y: Double)

object Point {
  implicit val pointDefault = Default withValue Point(0.0,0.0)
}

object Main {
  def main(args: Array[String]): Unit = {
    import Default.default
    println(default[Int])
    println(default[BigDecimal])
    println(default[Option[String]])
    println(default[String])
    println(default[Person])
    println(default[Point])
  }
}

上述实现的行为与预期的一样,除了BigInt和BigDecimal(以及其他用户定义类型为Numeric的实例)的情况,其中它给出null而不是零.我应该怎么做才能使forNumeric优先于forAnyRef并且我得到了我期望的行为?

解决方法

选择forAnyRef隐式是因为根据Scala引用的§6.26.3“重载分辨率”,它比forNumeric更具体.有一种方法可以通过将其移动到Default扩展的特征来降低其优先级,如下所示:

trait LowerPriorityImplicits extends LowestPriorityImplicits {
  this: Default.type =>

  implicit def forAnyRef[A >: Null] = withValue(null: A)

}

object Default extends LowerPriorityImplicits {
  // as before,without forAnyRef
}

但这只是技巧的一部分,因为现在forAnyRef和forNumeric都是彼此特定的,你会得到一个含糊不清的隐含错误.这是为什么?好吧,forAnyRef得到一个额外的特异性点,因为它对A:A>:Null有一个非平凡的约束.那么,为了向forNumeric添加一个非平凡的约束,你可以做的是在默认值中将它加倍:

implicit def forNumericVal[A <: AnyVal: Numeric] = withValue(implicitly[Numeric[A]].zero)

implicit def forNumericRef[A <: AnyRef: Numeric] = withValue(implicitly[Numeric[A]].zero)

现在,这个额外的约束使得NumericVal和forNumericRef对于Numeric可用的类型的forAnyRef更具体.

(编辑:李大同)

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

    推荐文章
      热点阅读