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

Typesafe Swing事件 – “在运行时无法检查此类型测试中的外部引

发布时间:2020-12-16 09:20:26 所属栏目:安全 来源:网络整理
导读:我正在实现一个Swing组件,我想克服Reactor的####无类型.所以我以为这样会工作: trait Foo[A] extends scala.swing.Publisher { final case class Bar(parent: Vector[A],children: A*) extends scala.swing.event.Event}trait Test { val foo: Foo[Int] foo
我正在实现一个Swing组件,我想克服Reactor的####无类型.所以我以为这样会工作:

trait Foo[A] extends scala.swing.Publisher {
  final case class Bar(parent: Vector[A],children: A*) extends scala.swing.event.Event
}

trait Test {
  val foo: Foo[Int]

  foo.reactions += {
    case foo.Bar(parent,children) => {
      println(parent.sum - children)
    }
  }
}

不幸的是,给我两个编译器警告:

The outer reference in this type test cannot be checked at run time.
  final case class Bar(parent: Vector[A],children: A*) extends scala.swing.event.Event
                   ^
The outer reference in this type test cannot be checked at run time.
    case foo.Bar(parent,children) => {
                ^

我应该忽略这些警告吗?我可以压制他们吗?我应该改变设计吗?

解决方法

在Scala中,内部类是“路径依赖”.

我将以你的代码为例.如果你有两个Foo [Int],称为foo和bar,那么foo.Bar是一个不同于bar.Bar的类型.请注意,这与Java的内部类的想法不同,其中foo.Bar和bar.Bar是相同的类型.

在任何情况下,JVM不直接支持内部类,所以在Java和Scala中,类Bar将编译为名为Foo $Bar的JVM类.内部类的实例几乎总是包含对其所有者的引用 – “外部引用”.

现在,当您在路径依赖类型(如代码中的一个)中有一个模式匹配时,Scala编译器将产生一个字符串,它有两件事情:它将检查该类(因此它将检查它接收到的对象是Foo $Bar的一个实例),它将检查外部引用(因此它将检查接收到的对象的外部引用是否为foo).

但是,在你的代码中,编译器找不到一个检查外部引用的方式,因为你已经将内部类定义为final.

所以,如果忽略该警告,那么你的模式将匹配所有Foo $Bar的实例,即使它们不属于foo.你会有一个比我更好的想法,这是否会是一个问题.

或者,您可以通过使内部课程非最终进行修复.

Ps,我不完全确定为什么Scala编译器无法检查最终内部类的外部引用,但是我发现如果一个内部类是final,那么外部的$是private,而如果它是非final的$是公开的编译器的内部组件可能值得一试,找出原因.

更新

事实证明这是一个已知的问题 – SI-4440.如果Scala编译器没有被使用(这是模糊的合法的,因为没有子类也可能使用它们),Scala编译器会丢弃最终内部类的外部引用.一个积极的后果是外部类可以被垃圾收集,而内部类仍在使用,所以Scala开发人员不愿重新引入外部引用,因为担心引入内存泄漏.

(编辑:李大同)

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

    推荐文章
      热点阅读