scala的语法非常有前途。我原以为scala不仅仅是简单的java,可以引入全新的编程范式,但是语法允许的许多特性在语义上是不正确的。因此,我开始寻找scala的限制和黑客来消除它们。虽然我只是编写一个测试项目以适应scala的方式和模式,但从其他角度来看。
主要的障碍是从jvm实现继承的类型擦除。我可以写一篇小文章,题为“擦除类型毁掉的十种美丽图案”。据说,类型擦除会污染仿制药,但我无意中发现了混药中的类型擦除。我认为scala中的mixin实现存在问题。
前言
trait T1
trait T2
trait B1 {
def typeMe(x:T1){}
}混合码破译
trait B2 extends B1 {
def typeMe(x:T1 with T2) {}
}将混合蛋白声明为独立特性的工作代码
trait T3 extends T1 with T2
trait B3 extends B1 {
def typeMe(x:T3) {}
}错误是:
error: name clash between defined and inherited member:
method typeMe:(x: T1 with T2)Unit and
method typeMe:(x: T1)Unit in trait B1
have same type after erasure: (x: $line12.$read#$iw#$iw#T1)Unit
def typeMe(x:T1 with T2)最好的解决办法是什么?引入新的特性是冗长的(特别是对于大的混合链),并导致类型不兼容。添加模拟隐式参数也不是灵丹妙药,因为它增加了开销。
最新情况:
很抱歉,我问错问题了。我更感兴趣的是所描述的错误的性质,而不是它的解决办法。类型擦除在哪里发生?在被认为是类型擦除源的代码中,我看不到泛型。编译器行为背后的机制是什么?
发布于 2012-02-28 02:41:55
你想做的事情有几个问题。
首先,类型擦除发生的时间并不重要。这是因为类型擦除的概念是,无论您在计算之前还是之后删除类型,结果都应该是相同的。对于JVM语言,在编译时iinm会发生一些擦除。
其次,您的“工作”代码实际上并不像您认为的那样工作。这需要对子类型、协方差和对比方差有一点了解。(Foo <: Bar的意思是"Foo是Bar的一个子类型“,或者非正式地说,"Foo比Bar更具体”)。函数在它们的输入中是反变的,在它们的输出中是协变的,这意味着函数A => B <: W => V只在W <: A和B <: V的情况下。
现在考虑一下您的功能:
B1.typeMe(x:T1)
B3.typeMe(x:T3)B3.typeMe的输入是T3,而B1.typeMe的输入类型是T1。但是,T3 <: T1 (T3比T1)更具体,因此B3.typeMe的类型不能是B1.typeMe类型的子类型。相反,它们只是被认为是单独的功能,有时会发生一些令人毛骨悚然的沉默。老实说,这可能会发出一个错误或至少一个警告。谢天谢地,另一个版本做到了。
https://stackoverflow.com/questions/9472031
复制相似问题