scala - 构造函数(特征)不能应用于(类扩展特征)

标签 scala inheritance constructor 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)) ) )
    }
}

(就我的目的而言,除法不是必需的,减法是通过添加某些东西的负数来解决的。我打算在完成完整的字符串解析器后在此处删除辅助构造函数,这是一个不处理括号的快速解决方案)

在尝试将字符串解析为方程式的过程中,我创建了一个 Array[Array[Equation]],因为 Equations 中的 Equations 让我可以处理括号的运算顺序。由于 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]])

知道我做错了什么吗?我尝试重写 Equation 的构造函数(见下文),但这给我带来了更多错误,而且看起来比必要的复杂:

class Equation [T <: Value] ( eq: Array[Array[T]] ) extends Value { ... }

最佳答案

您观察到的问题归结为 Scala 中的 Arrayinvariant 的。例如:

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 中是不变的,这意味着你不能分配一个Collection[Derived] 类型的值转换为预期类型 Collection[Base] 的变量/参数,反之亦然。

数组是不变的有很好的理由:数组是可变的,如果它不是不变的并且例如协变,那么就有可能违反打字保证:

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

自然,对于“嵌套”类型的构造函数,不变性被传播,因此您不能将 Array[Array[Equation]] 分配给 Array[Array[Value]]

解决这个问题的最简单方法是使用一些协变集合(它必然是不可变的):

class Equation(eq: Vector[Vector[Value]]) extends Value {
  ...
}

Vector[T] 是一个不可变集合,其类型参数是协变的,因此可以将 Vector[Derived] 分配给 Vector[基础]。因此,您的代码将起作用。

关于scala - 构造函数(特征)不能应用于(类扩展特征),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56589597/

相关文章:

Scala/Spark 版本兼容性

c# - 多重继承

constructor - 将强制数据传递给 Kotlin 中的父类(super class)

c++ - 如果只有一个成员没有默认构造函数,为什么 union 有一个已删除的默认构造函数?

c++ - 如何在构造函数的初始化列表中初始化共享指针?

scala - 如何在 Dockerfile 中为 sbt 插件添加自定义命令

scala - 在Scala中,您可以使匿名函数具有默认参数吗?

scala - 如何以惯用的方式在 Scala 中进行空值检查?

c# - 从 C# 中的结构继承的梦想

c# - 解决继承问题