构造函数(特征)不能应用于(class 扩展特征)
Constructor (trait) can't be applied to (class extending trait)
我有一个特征 "Value" 和一个扩展 class "Equation",像这样:
trait Value {
def apply(in: Input): Int
}
class Equation ( eq: Array[Array[Value]] ) extends Value {
override def apply (in: Input) = {
eq.map(addend => addend.map( _(in) ).fold(1)(_ * _) ).fold(0)(_ + _)
}
def this(eq: String) = {
this( eq.replace("-", "+-").split('+').map( _.split('*').map(s => Value(s)) ) )
}
}
(为了我的目的,除法不是必需的,减法是通过添加某些东西的负版本来解决的。我打算在完成完整的字符串解析器后删除这里的辅助构造函数,这是一个无法处理的快速解决方案括号)
在尝试将字符串解析为方程式的过程中,我创建了一个数组[Array[Equation]],因为方程式中的方程式让我可以处理括号的运算顺序。由于 Equation 是一个值,我希望我可以将此 Array[Array[Equation]] 传递给 Equation 的构造函数,但随后出现以下错误:
overloaded method constructor Equation with alternatives:
[error] (eq: String)spekular.misc.Equation <and>
[error] (eq: Array[Array[spekular.misc.Value]])spekular.misc.Equation
[error] cannot be applied to (Array[Array[spekular.misc.Equation]])
知道我做错了什么吗?我尝试重写方程式的构造函数(见下文),但这给我带来了更多错误,而且看起来比必要的更复杂:
class Equation [T <: Value] ( eq: Array[Array[T]] ) extends Value { ... }
您观察到的问题归结为 Scala 中的 Array
是 不变的 。例如:
trait Base
class Derived extends Base
val bases: Array[Base] = Array[Derived](new Derived)
这段代码产生的错误信息更清楚一点:
type mismatch;
found : Array[Derived]
required: Array[Base]
Note: Derived <: Base, but class Array is invariant in type T.
您可以找到有关方差的更多信息,例如here。这个想法基本上是,如果某些类型 Collection[T]
在其类型参数 T
中是不变的 ,这意味着您不能分配类型 [=17] 的值=] 到预期类型 Collection[Base]
的 variable/parameter,反之亦然。
数组是不变的有很好的理由:数组是可变的,如果它不是不变的,例如协变,那么就有可能违反类型保证:
trait Base
class Derived1 extends Base
class Derived2 extends Base
val derived1s: Array[Derived1] = Array(new Derived1)
val bases: Array[Base] = derived1s
bases(0) = new Derived2 // putting Derived2 in an array of Derived1
val derived1: Derived1 = derived1s(0) // type mismatch
自然地,对于 "nested" 类型构造函数,不变性被传播,因此您不能将 Array[Array[Equation]]
分配给 Array[Array[Value]]
。
解决这个问题的最简单方法是使用一些 协变 集合(它必须是不可变的):
class Equation(eq: Vector[Vector[Value]]) extends Value {
...
}
Vector[T]
作为一个不可变集合,其类型参数是协变的,因此可以将 Vector[Derived]
赋值给 Vector[Base]
。因此,您的代码将起作用。
我有一个特征 "Value" 和一个扩展 class "Equation",像这样:
trait Value {
def apply(in: Input): Int
}
class Equation ( eq: Array[Array[Value]] ) extends Value {
override def apply (in: Input) = {
eq.map(addend => addend.map( _(in) ).fold(1)(_ * _) ).fold(0)(_ + _)
}
def this(eq: String) = {
this( eq.replace("-", "+-").split('+').map( _.split('*').map(s => Value(s)) ) )
}
}
(为了我的目的,除法不是必需的,减法是通过添加某些东西的负版本来解决的。我打算在完成完整的字符串解析器后删除这里的辅助构造函数,这是一个无法处理的快速解决方案括号)
在尝试将字符串解析为方程式的过程中,我创建了一个数组[Array[Equation]],因为方程式中的方程式让我可以处理括号的运算顺序。由于 Equation 是一个值,我希望我可以将此 Array[Array[Equation]] 传递给 Equation 的构造函数,但随后出现以下错误:
overloaded method constructor Equation with alternatives:
[error] (eq: String)spekular.misc.Equation <and>
[error] (eq: Array[Array[spekular.misc.Value]])spekular.misc.Equation
[error] cannot be applied to (Array[Array[spekular.misc.Equation]])
知道我做错了什么吗?我尝试重写方程式的构造函数(见下文),但这给我带来了更多错误,而且看起来比必要的更复杂:
class Equation [T <: Value] ( eq: Array[Array[T]] ) extends Value { ... }
您观察到的问题归结为 Scala 中的 Array
是 不变的 。例如:
trait Base
class Derived extends Base
val bases: Array[Base] = Array[Derived](new Derived)
这段代码产生的错误信息更清楚一点:
type mismatch;
found : Array[Derived]
required: Array[Base]
Note: Derived <: Base, but class Array is invariant in type T.
您可以找到有关方差的更多信息,例如here。这个想法基本上是,如果某些类型 Collection[T]
在其类型参数 T
中是不变的 ,这意味着您不能分配类型 [=17] 的值=] 到预期类型 Collection[Base]
的 variable/parameter,反之亦然。
数组是不变的有很好的理由:数组是可变的,如果它不是不变的,例如协变,那么就有可能违反类型保证:
trait Base
class Derived1 extends Base
class Derived2 extends Base
val derived1s: Array[Derived1] = Array(new Derived1)
val bases: Array[Base] = derived1s
bases(0) = new Derived2 // putting Derived2 in an array of Derived1
val derived1: Derived1 = derived1s(0) // type mismatch
自然地,对于 "nested" 类型构造函数,不变性被传播,因此您不能将 Array[Array[Equation]]
分配给 Array[Array[Value]]
。
解决这个问题的最简单方法是使用一些 协变 集合(它必须是不可变的):
class Equation(eq: Vector[Vector[Value]]) extends Value {
...
}
Vector[T]
作为一个不可变集合,其类型参数是协变的,因此可以将 Vector[Derived]
赋值给 Vector[Base]
。因此,您的代码将起作用。