Чому модуль, що повертає метод, може бути замінений на метод String return String, коли типи повернення явно не вказані?


11

Я працював над прикладами коду з глави "Особливості програмування" в 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

Хто-небудь може допомогти пояснити, чому в першому випадку немає помилки компіляції.


Компілятор надрукував дійсну підказку, що ви намагаєтеся замінити метод, який має інший тип результату.
Андрій

Так, але моє питання, чому це потрапило через компілятор у 1-й справі
Шаніл

1
Правило, будьте завжди чіткими щодо типів повернення_ (особливо в загальнодоступних API) _. Вибір типу чудово підходить для локальних змінних, нічого іншого.
Луїс Мігель Мехіа Суарес

Відповіді:



6

моє запитання, чому це потрапило через компілятор у 1-му випадку

Коли ви не вказали тип повернення прямо, він був зроблений з типом, який він повинен мати для overrideроботи.

Це виявилося Unit.

Оскільки Stringможуть бути призначені значення (значення виразу, що складає тіло функції) Unit, компілятор задоволений.


1
Однак я хочу знати, чому явний тип повернення Stringбуло відхилено. У Java (і я думаю, що і в Scala теж) вам дозволяється звузити тип повернення при переопределенні. Наприклад, коли батьківський метод повертається Number, ви можете повернутися Integer. Може void/ Unitє особливим.
Тіло

1
Це компілює, наприклад:trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
Тіло

2
Ви можете звузити тип повернення до підтипу; але ви не можете звузити його до типу, який може бути неявно перетворений у тип повернення перекритого методу. Stringto Unitбільше схожий на другий, навіть якщо це не зовсім так .
Олексій Романов

2
На рівні байт-коду також немає зворотного типу повернення, насправді є два способи Frog: def philosophize : Integerі def philosophize : Number. Другий фактично перекриває Philosophicalметод 's (і називає перший). Те ж саме, безумовно, можна зробити для void/ нічого іншого, дизайнери просто вирішили цього не робити.
Олексій Романов

2
1. Java робить те саме. 2. Так, у байт-коді ви можете. Див., Наприклад, stackoverflow.com/questions/18655541/… та stackoverflow.com/questions/58065680/… .
Олексій Романов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.