为何Scala中方法参数可写List[I],泛型参数却无法如此定义?
问题原因解析
这个编译错误的核心问题在于泛型参数的定义规则——Scala要求 trait/class 的泛型参数必须是独立的类型变量(也就是简单的标识符,比如I、M),而不能是复合类型表达式(比如List[I])。
咱们拆解两个例子对比来看:
第一个例子(合法写法)
abstract trait Repository[I,M] { def getOneById(id: List[I]): Option[M] }
这里的I是被明确声明为泛型参数的类型变量,编译器知道它代表任意类型。所以方法里的List[I]是完全合法的——它表示“元素类型为I的List”,I的定义来自 trait 的泛型参数列表。
第二个例子(错误写法)
abstract trait Repository[List[I],M] { def getOneById(id: List[I]): Option[M] // 编译错误:cannot resolve I }
这里的问题有两个:
- 泛型参数列表里的
List[I]不是合法的类型变量——Scala只允许单个标识符作为泛型参数,不能带类型构造器(比如List[...]这种结构)。 - 此时
I根本没有被声明为泛型参数,编译器完全不知道I指代什么,自然会报错“无法解析I”。
正确的写法(如果想让泛型关联List类型)
如果你希望Repository的泛型和List绑定,有两种常见思路:
思路1:保留元素类型的泛型参数(最常用)
和第一个例子一样,先声明元素类型I,方法参数直接用List[I]:
abstract trait Repository[I,M] { def getOneById(id: List[I]): Option[M] }
思路2:直接约束泛型为List类型
如果不需要关心List的元素类型,只想限定第一个泛型参数是List,可以这么写:
abstract trait Repository[L <: List[_], M] { def getOneById(id: L): Option[M] }
如果同时需要元素类型和List类型,就把两者都声明为泛型参数:
abstract trait Repository[I, L <: List[I], M] { def getOneById(id: L): Option[M] }
内容的提问来源于stack exchange,提问作者Manu Chadha
相关产品推荐
相关产品推荐

