Scala 2.11关联存在类型参数编译错误技术问询
解决Scala 2.11中存在类型参数关联的编译错误
这个问题我太熟了——Scala 2.11里处理带关联约束的存在类型时很容易踩这个坑。让我给你拆解清楚问题出在哪,以及怎么解决:
错误原因
你定义的DataItem[D, P <: DataProcessor[D]]有一个关键约束:第二个类型参数P必须是对应第一个参数D的DataProcessor子类。但当你写Set[DataItem[_, _]]时,两个_是完全独立的通配符——编译器会把它们当成两个毫无关系的类型_$1和_$2,自然无法保证_$2 <: DataProcessor[_$1],所以直接违反了DataItem的类型参数约束,导致编译失败。
解决方案
方法1:用存在类型绑定关联两个参数
你需要明确告诉编译器:集合里的每个DataItem都满足“存在某个D,且P是DataProcessor[D]的子类”这个约束。Scala的forSome语法就是用来做这件事的:
def computeDataFromItems(items: Set[DataItem[D, P] forSome { type D; type P <: DataProcessor[D] }]) = items collectFirst { case DataItem(s, _) => s.computeData() }
如果觉得这段类型声明太长,可以先定义一个类型别名简化代码:
// 定义一个别名,代表所有符合约束的DataItem实例 type ValidDataItem = DataItem[D, P] forSome { type D; type P <: DataProcessor[D] } def computeDataFromItems(items: Set[ValidDataItem]) = items collectFirst { case DataItem(s, _) => s.computeData() }
方法2:用嵌套通配符缩小范围
如果你不想写冗长的存在类型,也可以通过嵌套通配符来暗示约束(这个写法在这个场景下足够严谨):
def computeDataFromItems(items: Set[DataItem[_, _ <: DataProcessor[_]]]) = items collectFirst { case DataItem(s, _) => s.computeData() }
这里第二个通配符_ <: DataProcessor[_]明确了P必须是某个DataProcessor的子类,编译器会在模式匹配时自动推断出P和D的关联关系,顺利通过编译。
测试验证
我们可以写个简单的测试代码验证修改后的逻辑:
// 实现一个具体的DataProcessor case class StringProcessor() extends DataProcessor[String] { override def computeData(): String = "Processed string data" } // 创建符合约束的DataItem实例 val validItem = DataItem(StringProcessor(), "Raw input") val items = Set(validItem) // 调用方法,返回预期结果 computeDataFromItems(items) // 输出: Some("Processed string data")
内容的提问来源于stack exchange,提问作者Luigi Sgro
相关产品推荐
相关产品推荐

