【问题标题】:Specifying the subtype of a Generic in Scala在 Scala 中指定泛型的子类型
【发布时间】:2011-10-10 14:29:51
【问题描述】:

考虑下面的例子,它应该打印 8。为什么A.Value + B.Value 认为B.Value 应该是一个字符串?我该如何解决?

object Catano extends App {
  val const3 = new Constant(3)
  val const5 = new Constant(5)

  val block = new Arithmetic(const3.Result, const5.Result)

  println(block.Sum.Value)
}

class Block

class Arithmetic[T: Numeric](val A: Connector[T], val B: Connector[T]) extends Block {
  def Sum = new Connector({ A.Value + B.Value })
}

class Constant[T](x: T) extends Block {
  def Result = new Connector({ x })
}

class Connector[T](f: => T) {
  def Value: T = f
}

出于类型安全的原因,以下操作应该会失败并出现类型异常:

  val const3 = new Constant("ping")
  val const5 = new Constant("pong")

  val block = new Arithmetic(const3.Result, const5.Result)

【问题讨论】:

  • 这确实为我打印 8,前提是我导入 scala.math.Numeric.Implicits_ 此外,您的大写字母显然是 C#-ish。成员vals 和defs 一般以小写开头。

标签: generics scala variance


【解决方案1】:

您的问题可以通过以下方式重现:

class C[T: Numeric] {def add(a: T, b: T) = a+b }
error: type mismatch;
found   : T
required: String

那里发生了什么:在 scala 中和在 java 中一样,你可以做 String + 任何东西,也可以做任何东西 + String。因为,与 java 不同,perators 只是普通的方法调用,这似乎意味着每种类型都有一个对应的 + 方法。当然不是这样,因为java类型没有这样的方法。我们所拥有的是Predef 中的implicit def any2StringAdd(x: Any),这使得+ 可以通过隐式转换获得。在您的代码中,这是唯一可用的 +,这就是为什么它抱怨 B.Value is not a String

现在为什么预期的+ 不可用? T:Numeric 要求在隐式范围内有一个 Numeric[T] 值。它没有说明 T 应该是什么类型,以及 T 上可用的方法。这个Numeric[T] 实例有一个def plus(x: T, y: T): T 方法。仅此一项并不能使+ 在 T 上可用。您可以直接调用 plus,但这并不方便。幸运的是,委托给plus+ 可以通过隐式转换添加(就像+(String)Predef 中一样),只要您在范围内添加一些隐式:

import Numeric.Implicits._

【讨论】:

    【解决方案2】:

    这行得通:

    class Arithmetic[ T <: Int] (val A: Connector[T], val B: Connector[T]) extends Block {
      def Sum = new Connector({ A.Value + B.Value })
    }
    

    数字没有+ 函数

    【讨论】:

    • 这是如何解决我的问题的一个简单而好的例子 :-)
    • 考虑到 Int 不能被子类化,T <: int>
    • 是的……是的……指定 Int 的正确方法是什么,并且只指定 Int?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    相关资源
    最近更新 更多