Я работал над примерами кода из главы «Особенности в программировании в Scala Edition1» https://www.artima.com/pins1ed/traits.html
и наткнулся на странное поведение из-за моей опечатки. Несмотря на то, что переопределенный метод признака ниже фрагмента кода не дает никакой ошибки компиляции, хотя возвращаемые типы переопределенного метода отличаются Unit
от String
. Но после вызова метода объекта он возвращает Unit, но ничего не печатает.
trait Philosophical {
def philosophize = println("I consume memory, therefore I am!")
}
class Frog extends Philosophical {
override def toString = "green"
override def philosophize = "It aint easy to be " + toString + "!"
}
val frog = new Frog
//frog: Frog = green
frog.philosophize
// no message printed on console
val f = frog.philosophize
//f: Unit = ()
Но когда я даю явный тип возвращаемого значения в переопределенном методе, он выдает ошибку компиляции:
class Frog extends Philosophical {
override def toString = "green"
override def philosophize: String = "It aint easy to be " + toString + "!"
}
override def philosophize: String = "It aint easy to be " + toString +
^
On line 3: error: incompatible type in overriding
def philosophize: Unit (defined in trait Philosophical);
found : => String
required: => Unit
Может кто-нибудь помочь объяснить, почему нет ошибки компиляции в первом случае.
scala
overriding
traits
Shanil
источник
источник
Ответы:
Когда ожидается тип
Unit
, любое значение может быть принято :источник
Когда вы не указали тип возвращаемого значения явно, он был выведен по типу, необходимому для
override
работы.Это оказалось
Unit
.Поскольку
String
значения (значение выражения, составляющего тело функции) могут быть назначеныUnit
, компилятор доволен.источник
String
был отклонен. В Java (и я думаю, что и в Scala) вам разрешено сужать тип возвращаемого значения при переопределении. Например, когда родительский метод возвращаетсяNumber
, вы можете вернутьсяInteger
. Возможноvoid
/Unit
особенный.trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
String
чтобыUnit
больше похож на второй, даже если это не совсем то.Frog
:def philosophize : Integer
иdef philosophize : Number
. Второй фактически переопределяетPhilosophical
метод (и вызывает первый). То же самое можно сделать и дляvoid
всего остального, дизайнеры просто решили этого не делать.