Есть ли в любом случае маркировка в сигнатуре метода, она должна возвращать подтип определенного типа - PullRequest
0 голосов
/ 25 октября 2019

Я не могу понять, почему это не компилируется:

abstract class Animal {}

class Duck extends Animal {}

object Main {
  def fooBar[T <: Animal ]():T = {
    return new Duck()
  }
}

Почему я получаю ошибку компиляции, которая:

Обязательно: T

Найдено: Утка

Разве T <: Animal не означает, что мне просто нужно вернуть подтип Animal? & Утка это подтип? Это то, что у меня было много проблем с пониманием. Есть ли в любом случае маркировка в сигнатуре метода, она должна возвращать подтип определенного типа?

Ответы [ 3 ]

4 голосов
/ 25 октября 2019

Разве T <: Animal не означает, что мне просто нужно вернуть подтип Animal?

Нет. Это означает, что вы должны вернуть T, выбранный вызывающей стороной вашего метода. Вызывающая сторона ограничена, чтобы сделать это подтипом Animal, но это может быть Duck, Dog или Cat.

Вы не можете просто вернуть Duck, потому чтовызывающая сторона, возможно, хотела получить Cat.

Без какого-либо дополнительного параметра, сообщающего вам, что должно быть возвращено, единственный способ реализовать это - вернуть Nothing, т.е. выдать исключение, вернуть null(но не делайте этого в Scala) или никогда не возвращайтесь вообще.

Мне просто нужно вернуть подтип Animal

Если вы хотитечто тип возвращаемого значения должен быть объявлен как Animal.

Вы всегда можете вернуть Duck, когда требуется Animal.

, почему я не могу указать, вы можетевозвращает подтип Animal, но не само Animal!

Нет способа указать это в системе типов. И в этом тоже не должно быть необходимости. Если вы говорите, что вам нужен Animal, все, что реализует интерфейс, определенный этим, должно быть достаточно хорошим.

Возможные «обходные пути»:

  • make Animal anabstract класс. Тогда самого экземпляра Animal не может быть, и все экземпляры будут экземплярами подкласса.
  • имеют еще один trait и объявляют тип как ActualAnimal или Animal with ActualImplementation. Но это было бы дополнительной работой с вашей стороны, чтобы добавить это trait, где это необходимо (и убедитесь, что вы не добавите его в Animal)
2 голосов
/ 25 октября 2019

Не могли бы вы объяснить вашу проблему?

Текущая подпись def fooBar[T <: Animal ]():T в основном гласит: «Какое бы животное ни попросил пользователь, я могу создать животное именно этого типа».

Эта функция не может иметь разумных реализаций.

1 голос
/ 25 октября 2019

Вы хотите сделать что-то вроде этого:

abstract class Animal {}

class Duck extends Animal {}

object Main extends App{

    def fooBar[T <: Animal](animal:T): T = {
      animal
    }
    println(fooBar[Animal](new Duck))
    println(fooBar[Duck](new Duck))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...