在此类型和其他类型之间不同的泛型类型上进行编译时检查

时间:2018-12-18 11:00:55

标签: compiler-construction typechecking

我已经了解了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)尽管第一个代码可能像超级字符一样工作,但我怀疑第二个代码也可能像超级字符一样工作,但是编译器非常渴望进行类型检查。为什么不能确定此检查也被推迟了。现在,我的解决方案是复制第二个类的代码,不再从第一个类扩展代码,而是复制第一个类的代码并添加多余的行。

0 个答案:

没有答案