Scala - 在参数化类型中使用参数化类型



我正在尝试编译以下代码:

case class Settings(settingsList:List[Setting])
abstract class Setting[T](name:String, value:T)

但编译器抱怨:

Error:(9, 54) class Setting takes type parameters
case class Settings(settingsList:List[Setting])
                                                     ^

但等效的 Java 代码可以顺利编译:

public class Settings {
    List<Setting> settingsList;
}
abstract class Setting<T> {
    abstract T getValue();
    abstract String getName();
}

scala有什么不同,以至于它不允许这种行为?

你只需要一个通配符类型:

case class Settings(settingsList:List[Setting[_]])
abstract class Setting[T](name:String, value:T)

这等效于您的 Java 代码。

Java 已在版本 5 中通用化,AFAIK 为了向后兼容,您可以省略类型参数。此外,Java具有使用站点差异,这通常使这些东西非常烦人,而不是Scala中的使用站点差异。如果不进行更改,您可以在 Scala 中使用存在类型List[Setting[_]],但最好使用正确的方差:

case class Settings(settingsList: List[Setting[Any]])
abstract class Setting[+A](name: String, value: A)

等效的 Java 代码可以成功编译

没有类型参数Setting是原始类型。根据 Java 文档,

允许使用原始类型作为对旧代码兼容性的让步。强烈建议不要在将泛型引入 Java 编程语言后编写的代码中使用原始类型。Java 编程语言的未来版本可能会禁止使用原始类型。

用 Java 编写此内容的正确方法是

List<Setting<?>> settingsList;

而斯卡拉等价物是List[Setting[_]],正如其他答案所说。

最新更新