Как работает реализация ScalaNumber в отношении базового? - PullRequest
2 голосов
/ 19 мая 2011

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.

Я что-то упускаю из виду или здесь что-то особенное?

РЕДАКТИРОВАТЬ: Конечно, я пропустил что-то очевидное ... С вами все в порядке. Ко-вариантные типы возврата. Спасибо!

Ответы [ 2 ]

4 голосов
/ 19 мая 2011

В методах Java и Scala возвращаемые типы могут быть ковариантными при переопределении. То есть, если вы переопределите метод, вы можете сделать его возвращаемый тип подтипом возвращаемого типа переопределенного метода.

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
4 голосов
/ 19 мая 2011

Это просто ковариантный тип возврата , который разрешен как в Scala, так и на Java.

Обоснование этого: если класс Base обещает вернуть AЕсли сформировать определенный метод, то подкласс Derived <: Base соблюдает принцип подстановки Лискова , если он возвращает A или любой подкласс B <: A.Конечно, если BigInt#underlying возвращает BigInteger, это не проблема для клиентов ScalaNumber, которые могут надеяться только на простой Object.

...