加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为什么我们必须显式指定ClassTag类型类

发布时间:2020-12-16 18:16:55 所属栏目:安全 来源:网络整理
导读:现在 scala已经使用ClassTag类型类迭代了JVM类型的擦除修复,为什么它是一个选择加入,而不是让编译器总是捕获运行时检查的类型签名.使它具有隐式参数化类型约束将使得无论泛型参数声明如何都可以调用classTag [T]. 编辑:我应该澄清,我并不是说scala应该改变
现在 scala已经使用ClassTag类型类迭代了JVM类型的擦除修复,为什么它是一个选择加入,而不是让编译器总是捕获运行时检查的类型签名.使它具有隐式参数化类型约束将使得无论泛型参数声明如何都可以调用classTag [T].

编辑:我应该澄清,我并不是说scala应该改变幕后的签名,以便始终包含ClassTag.相反,我的意思是,因为ClassTag显示scala可以捕获运行时类型信息并因此避免类型擦除限制,为什么不能将该捕获隐含为编译器的一部分,以便该信息始终在scala代码中可用?

我怀疑它是向后兼容性,java生态系统兼容性,二进制大小或运行时开销相关,但这些只是猜测.

解决方法

实际上,向后兼容性将完全被破坏.如果你有一个简单的方法,如:

def foo[A](a: A)(implicit something: SomeType) = ???

然后假设在下一版本的Scala中,编译器突然将隐式ClassTags添加到具有类型参数的所有方法的签名中.这种方法会被打破.它被明确调用的任何地方,如foo(a)(someTypeValue)将不再起作用.二进制和源兼容性将消失.

Java的互操作性会很难看.假设我们的方法现在看起来像这样:

def foo[A : ClassTag](a: A) = ???

因为ClassTag是由Scala编译器生成的,所以使用Java中的这种方法会更加困难.你必须自己创建ClassTag.

ClassTag<MyClass> tag = scala.reflect.ClassTag$.MODULE$.apply(MyClass.class);
foo(a,tag);

我的Java可能不是100%正确,但你明白了.任何参数化的东西都会变得非常难看.好吧,它已经是需要一个隐式的ClassTag,但是那些必要的方法类会大大增加.

而且,在我们(至少)使用的大多数参数化方法中,类型擦除并不是一个问题.由于上述原因,我认为自动要求每个类型参数使用ClassTag会比它有所帮助更麻烦.

当然这会增加更多的编译器开销,因为它需要生成比通常更多的ClassTag.我不认为它会增加更多的运行时开销,除非ClassTag有所作为.例如,在下面的简单方法中,ClassTag并没有真正做任何事情:

def foo[A : ClassTag](a: A): A = a

我们也应该注意到它们也不完美.因此,添加它们并不是解决擦除问题的最终解决方案.

val list = List(1,"abc",List(1,2,3),List("a","b"))
def find[A: ClassTag](l: List[Any]): Option[A] =
    l collectFirst { case a: A => a }

scala> find[List[String]]
res2: Option[List[String]] = Some(List(1,3)) // Not quite! And no warnings,either.

将ClassTag添加到每个单独的类实例会增加开销,并且肯定也会破坏兼容性.它也在很多地方都不可能.我们不能只使用ClassTag注入java.lang.String.此外,我们仍然容易被擦除.在每个类中使用ClassTag字段实际上并不比使用getClass更好.我们可以进行比较

case a if(a.getClass == classOf[String]) => a.asInstanceOf[String]

但这非常丑陋,需要演员,而不一定是ClassTag要修复的内容.如果我用我的find方法尝试过类似的东西,它就行不通了.

// Can't compile
def find[A](l: List[Any]): Option[A] =
    l collectFirst { case a if(a.getClass == classOf[A]) => a.asInstanceOf[A] }

即使我想以某种方式使用ClassTag来制作它,它会从哪里来?我不能说a.classTag == classTag [A],因为A已被删除.我需要在方法调用站点上使用ClassTag.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读