Spe*_*lar 3 inheritance constructor scala traits
我有一个特征“ Value”和一个扩展类“ 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)) ) )
}
}
Run Code Online (Sandbox Code Playgroud)
(出于我的目的,没有必要进行除法,减法通过添加负数来解决。我打算在完成完整的字符串解析器后在此处删除辅助构造函数,这是一种不处理括号的快速解决方案)
在尝试将字符串解析为方程式的过程中,我创建了Array [Array [Equation]],因为方程式内部的方程式允许我处理括号的运算顺序。由于方程式是一个值,所以我希望可以将此Array [Array [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]])
Run Code Online (Sandbox Code Playgroud)
知道我在做什么错吗?我尝试重写方程式的构造函数(请参见下文),但这给了我更多的错误,而且似乎比必需的更为复杂:
class Equation [T <: Value] ( eq: Array[Array[T]] ) extends Value { ... }
Run Code Online (Sandbox Code Playgroud)
您观察到的问题归结为Array在Scala中是不变的。例如:
trait Base
class Derived extends Base
val bases: Array[Base] = Array[Derived](new Derived)
Run Code Online (Sandbox Code Playgroud)
此代码产生的错误消息更加清楚:
type mismatch;
found : Array[Derived]
required: Array[Base]
Note: Derived <: Base, but class Array is invariant in type T.
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到有关方差的更多信息。这个想法基本上是,如果某个类型的type参数Collection[T]不变,则意味着您不能将type的值分配给期望类型的变量/参数,反之亦然。TCollection[Derived]Collection[Base]
数组是不变的,这有很好的理由:数组是可变的,如果它不是不变的,例如是协变的,那么就有可能违反类型保证:
type mismatch;
found : Array[Derived]
required: Array[Base]
Note: Derived <: Base, but class Array is invariant in type T.
Run Code Online (Sandbox Code Playgroud)
自然地,对于“嵌套”类型的构造函数,不变性会传播,因此您不能分配Array[Array[Equation]]给Array[Array[Value]]。
解决此问题的最简单方法是使用一些协变集合(必须是不可变的):
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
Run Code Online (Sandbox Code Playgroud)
Vector[T],作为一个不可变集合,在其类型参数协变,因此它可以分配Vector[Derived]到Vector[Base]。因此,您的代码将起作用。