我已经了解了Scala编译器的某些行为,我对此有一个解释,我不确定我是不是正确的。对于编译器中当前所做的选择,我想获得有关行为和解释的正确见解,以及可能的不良行为示例。
下面的代码可以按预期的方式编译并运行:
trait T1[A]
{
type ReturnType = this.type
val returnValue : this.type = this
def apply(_x : A) : ReturnType
}
trait T2[A]
extends T1[Option[A]]
{
def apply(_x : A) : ReturnType
}
class C1[A]
extends T1[A]
{
def apply(_x : A) : ReturnType =
{
// some functionality
returnValue
}
}
class C2[A]
extends C1[Option[A]]
with T2[A]
{
def apply(_x : A) : ReturnType = apply(Some(_x))
}
但是,例如,更改type和returnValue行:
type ReturnType = String
val returnValue : String = ""
将导致以下消息:
<pastie>:23: error: name clash between defined and inherited member:
def apply(_x: Option[A]): T2.this.ReturnType in trait T1 and
def apply(_x: A): T2.this.ReturnType at line 23
have same type after erasure: (_x: Object)String
def apply(_x : A) : ReturnType
^
<pastie>:38: error: name clash between defined and inherited member:
def apply(_x: Option[A]): C2.this.ReturnType in class C1 and
def apply(_x: A): C2.this.ReturnType at line 38
have same type after erasure: (_x: Object)String
def apply(_x : A) : ReturnType = apply(Some(_x))
^
我的解释是,对this.type的类型检查被推迟,因为在声明中,不知道this.type的确切类型。仅超级类型是已知的。
我有两个问题:
1)我的假设正确吗?
2)尽管第一个代码可能像超级字符一样工作,但我怀疑第二个代码也可能像超级字符一样工作,但是编译器非常渴望进行类型检查。为什么不能确定此检查也被推迟了。现在,我的解决方案是复制第二个类的代码,不再从第一个类扩展代码,而是复制第一个类的代码并添加多余的行。