scala 中的特征中使用的抽象值有问题吗?

发布于 2024-12-11 04:19:46 字数 171 浏览 0 评论 0原文

我的

trait Invoker {
  val method: Method
}

Intellij IDEA 代码检查警告我“特征中使用的抽象值”。一切编译都很好。特征具有抽象值有什么问题吗?如果是这样,我应该如何指定该特征的所有扩展程序都必须定义方法属性?

I have

trait Invoker {
  val method: Method
}

Intellij IDEA code inspection is warning me that "Abstract value used in trait". Everything compiles fine. Is there something wrong with having an abstract value in a trait? If so, how should I specify that all extenders of the trait must define a method property?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

过度放纵 2024-12-18 04:19:46

这意味着以下奇怪之处:

trait A {
  val i: String
  def j: String
}

class C extends A {
  println ("val i = " + i)
  println ("def j = " + j)

  val i = "i"
  def j = "j"
}

val c = new C
// prints
// val i = null
// def j = j

因此,正如您所看到的,i 之前已初始化为其默认值(null for AnyRef)它最终被 C 中的构造函数覆盖。 (def 声明会立即重新引用。)

为了避免这种情况,必须将 val 初始化放在构造函数的开头(如果可能的话)。


以下情况下的额外奇怪之处(以及如何解决它)

现在考虑一下

trait A {
  val i: String
  def j: String
}

abstract class D extends A {
  println ("val i = " + i)
  println ("def j = " + j)
}

class C extends D {
  val i = "i"
  def j = "j"
}
val c = new C
// prints
// val i = null
// def j = null

,我们似乎不走运;看起来我们没有机会在超类 D 尝试之前初始化 val i def j打印它们。
为了解决这个问题,我们必须使用早期定义(§5.1.6 Scala 参考):

class C extends {
  val i = "i"
  def j = "j"
} with D

val c = new C
// prints
// val i = i
// def j = j

它有效!

What is meant by this is the following weirdness:

trait A {
  val i: String
  def j: String
}

class C extends A {
  println ("val i = " + i)
  println ("def j = " + j)

  val i = "i"
  def j = "j"
}

val c = new C
// prints
// val i = null
// def j = j

So, as you can see i is initialised to it default value (null for AnyRef) before it is finally overridden by the constructor in C. (def declarations are re-referenced immediately.)

To avoid this one would have to put the val initialisations to the beginning of the constructor, if possible.


Additional weirdness (and how to solve it) in the following case

Consider

trait A {
  val i: String
  def j: String
}

abstract class D extends A {
  println ("val i = " + i)
  println ("def j = " + j)
}

class C extends D {
  val i = "i"
  def j = "j"
}
val c = new C
// prints
// val i = null
// def j = null

Now we seem to be out of luck; it looks as if there is no chance for us to initialise val i and def j before our superclass D tries to print them.
In order to solve this problem, we must use Early definitions (§5.1.6 Scala reference):

class C extends {
  val i = "i"
  def j = "j"
} with D

val c = new C
// prints
// val i = i
// def j = j

And it works!

薄情伤 2024-12-18 04:19:46

在特征中使用抽象 val 有很多充分的理由。不幸的是,IntelliJ IDEA 没有区分这些,只是警告不要普遍使用它们。实际上,这意味着 IntelliJ IDEA 警告将被忽略。

There are plenty of good reasons to use an abstract val in a trait. Unfortunately, IntelliJ IDEA does not distinguish those and simply warns against their use universally. In practice, this means that IntelliJ IDEA warnings are ignored.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文