首页 > 解决方案 > Scala - 使用泛型类型参数的内部类型定义无法编译

问题描述

我正在尝试定义算术表达式树表示。DataElement 表示单个键值对。CalcElement 表示一对子(计算或数据)元素。对于 CalcElement,键是子元素中键的元组。CalcElement 的值是使用其 apply 方法的子元素值的组合。

以下代码无法编译,我正在努力弄清楚为什么它不应该编译。

trait DataElement[K] {
  type KeyType = K
  def key:KeyType
  def value:Double
}

trait CalcElement[OP1<:DataElement[_], OP2<:DataElement[_]] extends DataElement[(OP1#KeyType, OP2#KeyType)] //FIRST ERROR
{
  def op1: OP1
  def op2: OP2

  def apply: (OP1, OP2) => Double
  def unapplyFirst: (Double, OP1) => OP2
  def unapplySecond: (Double, OP2) => OP1

  def key: (OP1#KeyType, OP2#KeyType) = (op1.key, op2.key) // SECOND AND THIRD ERROR
  def value: Double = apply(op1, op2)
}

第一个错误是

Error:(12, 84) illegal inheritance;
 self-type CalcElement[OP1,OP2] does not conform to DataElement[(_$1, _$2)]'s selftype DataElement[(_$1, _$2)]
trait CalcElement[OP1<:DataElement[_], OP2<:DataElement[_]] extends DataElement[(OP1#KeyType, OP2#KeyType)]

第二个和第三个错误是

Error:(21, 46) type mismatch;
 found   : (some other)_$1(in type OP1)
 required: _$1(in type OP1)
  def key: (OP1#KeyType, OP2#KeyType) = (op1.key, op2.key)
Error:(21, 55) type mismatch;
 found   : (some other)_$2(in type OP2)
 required: _$2(in type OP2)
  def key: (OP1#KeyType, OP2#KeyType) = (op1.key, op2.key)

可以在这里帮助理解编译器的思维方式。

干杯

标签: scalagenerics

解决方案


在您的示例中, KeyType 在构造类型之前是未定义的。因此,OP1#KeyType 和 OP2#KeyType 将不起作用。

要么这样做:

trait CalcElement[OP1<:DataElement[Double], OP2<:DataElement[Double]] 
extends DataElement[(OP1#KeyType, OP2#KeyType)]

或这个:

trait CalcElement[X, Y, OP1<:DataElement[X], OP2<:DataElement[Y]] 
extends DataElement[(OP1#KeyType, OP2#KeyType)]

我无法理解的是,为什么需要传递 KeyType 来构造 DataElement?因为,计算可以是一棵树,所以为什么不能这样:

trait CalcElement[OP1<:DataElement[_], OP2<:DataElement[_]] 
extends DataElement[(OP1, OP2)]

?


推荐阅读