首页 > 解决方案 > 无论如何在方法签名中标记它应该返回特定类型的子类型

问题描述

我不明白为什么这不能编译:

abstract class Animal {}

class Duck extends Animal {}

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

为什么我会收到以下编译错误:

要求:T

发现:鸭子

并不T <: Animal意味着我只需要返回一个子类型Animal? & Duck 是一个子类型?这是我一直难以理解的事情。无论如何在方法签名中标记它应该返回特定类型的子类型?

标签: scalatypes

解决方案


并不T <: Animal意味着我只需要返回一个子类型Animal?

不,这意味着您必须返回 a T,由您的方法的调用者选择。调用者必须使其成为 的子类型Animal,但它可以是 a Duck、 aDog或 a Cat

你不能只返回一个Duck,因为调用者可能想要一个Cat

如果没有一些额外的参数来告诉您应该返回什么,实现它的唯一方法是返回Nothing,即抛出异常、返回null(但不要在 Scala 中这样做)或根本不返回。

我只需要返回一个子类型Animal

如果需要,返回类型应声明为Animal.

Duck当需要 an 时,您始终可以返回 a Animal

为什么我不能指定您可以返回 Animal 的子类型但不能返回 Animal 本身!

您无法在类型系统中指定它。而且也不应该真的需要它。如果您说您需要一个Animal,那么实现由它定义的接口的所有东西都应该足够好。

可能的“解决方法”:

  • Animal上课abstract。_ 那么它本身就不可能有任何实例Animal,所有实例都是子类实例。
  • 有另一个trait并将类型声明为ActualAnimalor Animal with ActualImplementation。但是在需要的地方添加它会是你的额外工作trait(并确保你不添加它Animal

推荐阅读