这是一个例子
def maybeeq[A <: String](x: A):A = x match {
case z:A => x
}
在编译期间产生了以下错误消息
错误:(27,12)scrutinee与模式类型不兼容; 找一个 必需:字符串 case z:A =&gt; X
我可以将任何最终类放入A的绑定中以重现错误。
为什么这会为非最终类编译但在最终版本中失败?为什么键入擦除不只是用String替换A?
编辑:
注意:这样的绑定允许我将String类型的值传递给'x'参数。所以'x'可以只是一个字符串而不必是字符串的子类型,所以我不是要求编译器使用不正确的签名编译方法。在现实世界的代码中,我只是将String放在A参数上,但从实验的角度来看,我很感兴趣为什么需要在现有限制(基于最终类性质)的基础上进行这样的额外限制。
答案 0 :(得分:4)
TBH这是一个关于编译器设计的问题,只能由实施此类检查的人员来回答
编译器测试套件中有a test requires such error to be shown。它与被丢弃的类型信息有关,其中具体类型无法分配给变量,但是从该测试的git blame
无法理解其原因。
但是,我会指出,仍然有很多方法可以满足A <: String
,而A
在编译时不知道String
为Null
。例如,Nothing
和val UhOh: { type T <: String } = new { type T = String }
implicitly[UhOh.T <:< String] // satisfies type bound
implicitly[UhOh.T =:= String] // won't compile - compiler cannot prove the type equality
满足它,位于Scala类型层次结构的底部。在类型匹配时明确禁止这两个。另一个例子涉及更多:
shapeless.tag
这类似于一些新型模式,例如: A =:= String
在所有这些可能性中,只有一个可以做任何合理的事情是String
,因为ClassTag
是唯一可以在运行时实际检查的类型。哦,除非你在匹配中使用泛型类型 - 它根本不起作用(至少在范围内没有<?php
header('Response.ContentType = "application/vnd.ms-excel"');
header('Content-Disposition: attachement; filename="xlxml.xml"');
echo '<root><name>sample_name</name></root>';
exit();
?>
),因为这些类型通过擦除来消除。
答案 1 :(得分:1)
最终课程无法扩展。因为def maybeeq[A <: String](x: A)
语法不正确,因为String
为final
,不应该有任何子类型从String
延伸。编译器巧妙地指出了这个问题。