scala.math.ScalaNumber
是一个Java文件,如下所示:
public abstract class ScalaNumber extends java.lang.Number {
protected abstract boolean isWhole();
public abstract Object underlying();
}
而scala.math.BigDecimal
通过以下方式实现它:
class BigDecimal(val bigDecimal: BigDec, val mc: MathContext)
extends ScalaNumber with ScalaNumericConversions with Serializable {
...
def underlying = bigDecimal
}
以及scala.math.BigInt
:
class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericConversions with Serializable {
...
def underlying = bigInteger
}
令人困惑的是,underlying
的类型为java.math.BigDecimal
/ java.math.BigInt
,而不是Object
。
我是否会错过一些非常明显的东西,或者这里有什么特别的东西?
编辑:当然我错过了一些明显的东西......你没事。共变体返回类型。谢谢!答案 0 :(得分:4)
它只是一个covariant return type,在Scala和Java中都是允许的。
它背后的基本原理是:如果一个类Base
承诺返回A
形成某个方法,那么子类Derived <: Base
会尊重Liskov substitution principle,如果它返回{{} 1}}或任何子类A
。当然,如果B <: A
返回BigInt#underlying
,则对于BigInteger
的客户来说这不是问题,他们可能只希望获得普通的ScalaNumber
。
答案 1 :(得分:4)
在Java和Scala方法中,返回类型在覆盖时可以是协变的。也就是说,如果重写一个方法,你可以使它的返回类型成为overriden方法的返回类型的子类型。
scala> class Foo { def method : Object = "foo" }
defined class Foo
scala> class Bar extends Foo {override def method : String = "bar" }
defined class Bar
scala> (new Foo).method
res0: java.lang.Object = foo
scala> (new Bar).method
res1: String = bar
scala> ((new Bar) : Foo).method
res2: java.lang.Object = bar