如何使用与别名类型匹配的案例类?当我从容器中取出CB等时,这就有效。
class DoStuff[TKey](
val c : Container[TKey]#CB
)
{
type CB = Container[TKey]#CB
type C1 = Container[TKey]#C1
type C2 = Container[TKey]#C2
c match {
case C1(e1) => e1 // - not found: value e1 - not found: value C1
case C2(e2) => e2 // - not found: value e2 - not found: value C2
}
}
trait Container[TKey]
{
abstract trait CB
case class C1(val e : AnyRef) extends CB
case class C2(val e : AnyRef) extends CB
}
谢谢!
答案 0 :(得分:8)
正确... Scala中的内部类有点繁琐。在我向您展示您提供的代码的重写版本之前,让我们尝试一个简单的示例。
case class Foo(x: Int) {
case class Bar(y: String)
}
现在,请考虑以下代码段:
val x = new Foo(1)
val y = new Foo(2)
val a = new x.Bar("one")
val b = new y.Bar("two")
a
和b
的最通用类型是Foo#Bar
,这意味着内部类Bar
具有Foo
类型的任何外部对象。但我们可以更具体地说a
的类型为x.Bar
且b
的类型为y.Bar
- 这意味着a
是一个实例具有外部对象Bar
的内部类x
,类似于b
。
通过调用typeOf(a)
和typeOf(b)
,您实际上可以看到类型不同,其中typeOf
是一个定义为此类的实用程序方法。 (它只是通过非常好的类型推断和Manifest
s的一些使用来给出其参数的类型)
def typeOf[T](x: T)(implicit m: scala.reflect.Manifest[T]) = m.toString
当内部对象保存对其封闭对象的引用时,不能实例化内部对象而不以某种方式指定其外部对象。因此,您可以调用new x.Bar("one")
,但不能调用new Foo#Bar("?")
- 因为在第二种情况下,您没有指定您尝试构造的新对象的内部对象是什么。
所以,让我们回到你的代码片段。在进行模式匹配时,实际上是在调用构造函数时 - 调用C1(e1)
时。由于C1
是Container[TKey]#C1
的别名,因此您尝试调用内部类的构造函数而不指定其外部对象,由于上述原因,该对象失败。我编写代码的方式如下:
trait Container[TKey] {
abstract trait CB
case class C1(val e : AnyRef) extends CB
case class C2(val e : AnyRef) extends CB
}
class DoStuff[TKey] (val c: Container[TKey], val element: Container[TKey]#CB) {
element match {
case c.C1(e1) => Some(e1)
case c.C2(e2) => Some(e2)
case _ => None
}
}
现在这个编译并希望它可以做你想要的。但要小心谨慎!由于类型擦除,Scala无法保证element
实际上属于c.CB
类型或d.CB
类型,其中CB
属于c
和d
{1}}碰巧是一样的。
考虑这个例子:
def matcher(arg: Foo#Bar) = {
arg match {
case x.Bar(n) => println("x");
case y.Bar(n) => println("y");
}
}
其中x
和y
与之前一样。尝试运行以下内容:
matcher(a)
matcher(b)
他们都打印x
!
因此我会重写代码以在容器中明确地拥有一个元素:
trait Container[TKey] {
abstract trait CB
case class C1(val e : AnyRef) extends CB
case class C2(val e : AnyRef) extends CB
val element: CB
}
class DoStuff[TKey](val c: Container[TKey]) {
c.element match {
case c.C1(e1) => Some(e1)
case c.C2(e2) => Some(e2)
case _ => None
}
}
希望有所帮助:)
- Flaviu Cipcigan