[以下编辑]
我有一个类层次结构,现在大致如下:
sealed trait Foo {
def method: Any
}
case class Bar extends Foo {
def method: Array[String] = // implementation
}
case class Baz extends Foo {
def method: Map[String, Array[String]] = // implementation
}
我给抽象方法一个返回类型Any
,因为case类的返回类型必然不同,但它们有着相似的目的。出于这个原因,我希望将其保留在特征中以模拟这种常见行为,这是我发现编译它的唯一方法。我意识到这违反了Scala的类型系统的精神,所以我问下面的第一个问题。
然后,另一个类需要一个Foo
的子类作为构造函数参数,除了以下内容之外我不知道如何表示这个:
class Qux(foo: Foo) {
val m = foo.method
...
...
}
稍后在类Qux
中有一些方法期望val m
具有与{{Bar
或Baz
的特定子类相对应的类型1}},但我收到像
Foo
所以我有几个问题:
... type mismatch;
[error] found : Any
[error] required: Array[String]
Qux
应该被视为来自m
或method
的特定Bar
返回的值,而不是Baz
的抽象方法? 编辑:采用@marios建议的方法(使用抽象类型成员)似乎是朝着正确方向迈出的一步,但现在会弹出类型不匹配。在课程Foo
中,我现在有
Qux
class Qux[X <: Foo](sc: SparkContext, val foo: X) {
val m: foo.A = foo.method
def process(rows: DataFrame) = foo match {
case Bar(sc, _) => BarProcessor(sc, m).doStuff(rows)
case Baz(sc, _) => BazProcessor(sc, m.keys).doStuff(rows, m.values)
}
}
例如,使用BarProcessor
实例化Array[String]
,而BazProcessor
需要Baz
&#39; s返回的值中的键值对method
要做的事情。但是,我现在遇到像
[error] Qux.scala:4: type mismatch;
[error] found : Qux.this.foo.A
[error] required: Array[String]
[error] case Bar(sc, _) => BarProcessor(sc, m).doStuff(rows)
[error] ^
当我Map
m
foo
Baz
为value keys is not a member of Qux.this.foo.A
时,我尝试拨打m
时会显示类似的错误(沿着Array[String]
行,等等。)。我了解A
并非真正 ...shared/service/cert.service
- ...shared/Service/cert.service
类型。但有没有办法告诉Scala&#34;翻译&#34;这成为理想的类型?
答案 0 :(得分:4)
您可以在特征中添加类型参数,如下所示:
sealed trait Foo[A] {
def method: A
}
case class Bar extends Foo[Array[String]] {
def method: Array[String]
}
case class Baz extends Foo[Map[String, Array[String]]] {
def method: Map[String, Array[String]]
}
答案 1 :(得分:4)
访问ADT中各个类型的更简单方法是使用抽象类型成员而不是泛型类型参数。
sealed trait Foo {
type A
def method: A
}
case object Bar extends Foo {
type A = Array[String]
def method: A = Array.empty[String]
}
case object Baz extends Foo {
type A = Map[String, Array[String]]
def method: A = Map.empty[String, Array[String]]
}
case class Qux[X <: Foo](foo: X) {
def m: X#A = foo.method
// You can then pattern match on m
def f = m match {
case a: Baz.A => a.size // Use Baz#A if Baz is a class and not an object
case b: Bar.A => b.size // Use Bar#A if Bar is a class and not an object
}
}
使用它(查看返回类型)
@ Qux(Baz).m
res6: Map[String, Array[String]] = Map()
@ Qux(Bar).m
res7: Array[String] = Array()