Scala Case 类与别名内部类型匹配编译错误?
如何使用与别名类型匹配的案例类?当我从容器中取出 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
}
谢谢!
How do I use case class matching with aliased types? This works when I pull CB etc out of Container.
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
}
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的...Scala 中的内部类有点繁琐。在向您展示您提供的代码的重写版本之前,让我们尝试一个简单的示例。
现在,考虑以下代码片段:
a
和b
最通用的类型是Foo#Bar
,这意味着内部类Bar
与Foo
类型的任何外部对象。但我们可以更具体地说,a
的类型是x.Bar
,b
的类型是y.Bar
- 这意味着a
是内部类Bar
和外部对象x
的实例,与b 类似
。实际上,通过调用
typeOf(a)
和typeOf(b)
可以看到类型是不同的,其中typeOf
是一个实用方法,定义为这样的。 (它只是通过相当好的类型推断和一些Manifest
的使用来给出其参数的类型)当内部对象保存对其封闭对象的引用时,您不能 实例化一个内部对象而不以某种方式指定其外部对象。因此,您可以调用
new x.Bar("one")
但不能调用new Foo#Bar("?")
- 就像在第二种情况下您没有调用t 指定您尝试构造的新对象的内部对象是什么。那么,让我们回到您的代码片段。当您进行模式匹配时,您实际上是在调用构造函数 - 当调用
C1(e1)
时。由于C1
是Container[TKey]#C1 的别名
您尝试调用内部类的构造函数而不指定其外部对象,但由于上述原因而失败。我编写代码的方式如下:现在可以编译了,希望它能达到您想要的效果。但请务必小心!由于类型擦除,Scala 无法保证
element
实际上是c.CB
类型或d.CB
类型,其中
恰好是相同的。c
和d
中的 CB考虑这个例子:
其中
x
和y
与以前一样。尝试运行以下命令:它们都打印
x
!因此,我将重写代码以在容器中显式包含一个元素:
希望它有帮助:)
-- Flaviu Cipcigan
Right... Inner classes in Scala are a bit fiddly. Let's try a simple example before I show you the rewritten version of the code you have provided.
Now, consider the following code snippet:
The most generic type of
a
andb
isFoo#Bar
, which means the inner classBar
with any outer object of typeFoo
. But we could be more specific in saying that the type ofa
isx.Bar
and the type ofb
isy.Bar
- which means thata
is an instance of the inner classBar
with the outer objectx
, similar forb
.You can actually see that the types are different by calling
typeOf(a)
andtypeOf(b)
, wheretypeOf
is a utility method defined as such. (it just gives the type of its argument by quite nice type inference and a bit of use ofManifest
s)As an inner object holds a reference to its enclosing object, you cannot instantiate an inner object without somehow specifying its outer object. Therefore, you can call
new x.Bar("one")
but you cannot callnew Foo#Bar("?")
- as in the second case you haven't specified what is the inner object for the new object you try to construct.So, let's return to your code snippet. When you are pattern matching, you are actually calling a constructor - when calling
C1(e1)
. AsC1
is an alias forContainer[TKey]#C1
you have tried to call a constructor of an inner class without specifying its outer object, which fails due to the reasons outlined above. The way I would write the code would be as follows:Now this compiles and hopefully it does what you want. But take this with great care! Due to type erasure, Scala cannot guarantee that the
element
is actually of typec.CB
or of typed.CB
where theCB
in the case ofc
andd
happen to be the same.Consider this example:
where
x
andy
are as before. Try running the following:They both print
x
!Therefore I would rewrite the code to explicitly have an element in the container:
Hope it helps :)
-- Flaviu Cipcigan