我正在Scala 2.10.0-M1中尝试以下操作:
trait Container {
type X
}
class Test[C <: Container](val c: C) {
def foo(x: c.X): C#X = x // this compiles fine
def bar(x: C#X): c.X = x // this does not compile
}
使用此表单时问题相同:
def bar[C <: Container](c: C)(x: C#X): c.X = x
我真的不明白为什么foo
编译而bar
不编译。
我认为c.X
和C#X
在这里应该是相同的。
此外,我不理解错误消息:
[error] found : x.type (with underlying type C#X)
[error] required: Test.this.c.X
[error] possible cause: missing arguments for method or constructor
[error] def bar(x: C#X): c.X = x // this does not compile
知道吗?
C#X
表示来自任何C
的X
。c.X
是指来自特定C
的X
,即c
。后者要具体得多!
例如,如果X
是一张账单,而c
是一个特定的客户,那么c.X
意味着该方法只接受来自(可能是)客户c
的账单。C#X
表示接受任何客户的任何账单。如果你想确保客户只收取自己的账单(至少在默认情况下),前者就是你想要的。
@Rex很好地解释了问题所在。以下是如何修复它。。。
如果能够作为类型c.X
的结果返回x
(即作为参数传递的特定c
的X
类型的值)是合理的,那么可以将其类型作为参数
def bar[C <: Container](c: C)(x: c.X): c.X = x
现在栏将只接受与特定值c
相关的类型为X
的值。如果这对你在酒吧的呼叫站点不起作用,那么你需要重新设计。
c.X
和C#X
肯定不一样——如果是,为什么两者都存在?
考虑这样一种情况,即a
和b
是C
的不同实例。根据定义,a.X
和b.X
是不同的,但都是C#X
。