【问题标题】:What are implicit objects?什么是隐式对象?
【发布时间】:2014-04-30 19:25:33
【问题描述】:

我正在阅读有关 type classes 的内容,其中提到了隐式对象:

object Math {
  trait NumberLike[T] {
    def plus(x: T, y: T): T
    def divide(x: T, y: Int): T
    def minus(x: T, y: T): T
  }
  object NumberLike {
    implicit object NumberLikeDouble extends NumberLike[Double] {
      def plus(x: Double, y: Double): Double = x + y
      def divide(x: Double, y: Int): Double = x / y
      def minus(x: Double, y: Double): Double = x - y
    }
    implicit object NumberLikeInt extends NumberLike[Int] {
      def plus(x: Int, y: Int): Int = x + y
      def divide(x: Int, y: Int): Int = x / y
      def minus(x: Int, y: Int): Int = x - y
    }
  }
}

它们是什么?它们在哪里被描述?我只在web 上找到了隐式类的定义,但没有找到隐式对象的定义。

【问题讨论】:

    标签: scala implicit


    【解决方案1】:

    在 Scala 中,对象和值的处理方式基本相同。可以将隐式对象视为在查找其类型的隐式的过程中找到的值。

    在您的示例中,如果隐式查找带有类型参数DoubleIntNumberLike 类型类,则会找到NumberLikeDoubleNumberLikeInt

    implicit object NumberLikeDouble extends NumberLike[Double]
    

    因此与

    大致相同
    implicit val NumberLikeDouble: NumberLike[Double] = new NumberLike[Double] { ...}
    

    implicit def NumberLikeDouble: NumberLike[Double] = new NumberLike[Double] { ...}
    

    val 一样,该类型只有一个值,不需要实例化。


    一个简单的用例:

    import Math.NumberLike
    
    def sum[A](x: A, y: A)(implicit nl: NumberLike[A]) = nl.plus(x, y)
    
    sum(4, 5)   // finds NumberLikeInt
    

    【讨论】:

    • 隐式 val 和隐式 def 等效声明之间有什么区别吗?还是这三个隐式声明(隐式对象、def、val)完全可以互换?
    • objectval 变体只创建一次值,而使用def,您将在每次查找NumberLike 时实例化它。对于无状态类型类(无值或类型参数),因此使用objectval 更有意义。可以说,object 创建了一个“适当的”类,而在这种情况下,val 创建了一个匿名子类。
    • 感谢您的澄清,所以 object 和 val 在所有方面都是完全等价的?
    • 除非您将成员添加到类型中。例如,val Foo = new { def bar = 33 }。如果你调用Foo.bar,Scala 必须使用运行时反射来处理该方法,并且它已被弃用。在这些情况下,使用object Foo { def bar = 33 } 会创建一个包含该方法的“真实”类描述。
    【解决方案2】:

    借助隐式对象,您可以定义:

    def mymethod[T : NumberLike](value: T): T = {
      implicitly[NumberLike[T]].plus(value, value)
    }
    

    这允许您在 Double 和 Floats 上调用您的方法,因为您有对象来处理它们。

    scala> mymethod(1.0)
    res0: Double = 2.0
    
    scala> mymethod(2)
    res0: Int = 4
    
    scala> mymethod("test") //Error
    

    【讨论】:

      猜你喜欢
      • 2011-01-07
      • 2021-03-23
      • 1970-01-01
      • 2018-07-20
      • 1970-01-01
      • 2010-10-30
      • 2011-06-05
      • 2021-04-20
      • 2014-09-05
      相关资源
      最近更新 更多