我正在尝试编译以下代码:
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[_]]
,正如其他答案所说。