Scala 子案例类参数名称与父案例类参数名称冲突

发布于 2024-12-26 04:23:19 字数 371 浏览 1 评论 0原文

让我们假设我们有以下两个类:

abstract case class MyParent(param: Int) {
   // ...
}

case class MyChild(param: Int) extends MyParent(param: Int) {
   // ...          ^^^^^                        ^^^^^
}

使它们成为两个 case 类会导致两个 param 使用位置出现错误,这表明它需要 override 修饰符来覆盖来自父类的值。这对我来说看起来很奇怪..为什么我必须在这里发明其他参数名称..为什么要强制执行这个顺序?利润在哪里?

Let us assume we have the two following classes:

abstract case class MyParent(param: Int) {
   // ...
}

case class MyChild(param: Int) extends MyParent(param: Int) {
   // ...          ^^^^^                        ^^^^^
}

Making them both case classes resulted in an error in both param usage places, which says that it needs the override modifier that will override the value from the parent class. This looks strange to me.. why do I have to invent other param names here.. why is this order of things enforced? Where is the profit?

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

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

发布评论

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

评论(4

め七分饶幸 2025-01-02 04:23:19

您永远不应该从另一个案例类派生一个案例类!

在以 scala -deprecation 开头的 REPL 中尝试此操作:

scala> case class Foo(foo: String)
defined class Foo

scala> case class Bar(override val foo: String) extends Foo(foo)
<console>:9: warning: case class `class Bar' has case ancestor `class Foo'.  Case-to-case inheritance has potentially dangerous bugs which are unlikely to be fixed.  You are strongly encouraged to instead use extractors to pattern match on non-leaf nodes.

You never should derive a case class from another case class!

Try this in a REPL started with scala -deprecation:

scala> case class Foo(foo: String)
defined class Foo

scala> case class Bar(override val foo: String) extends Foo(foo)
<console>:9: warning: case class `class Bar' has case ancestor `class Foo'.  Case-to-case inheritance has potentially dangerous bugs which are unlikely to be fixed.  You are strongly encouraged to instead use extractors to pattern match on non-leaf nodes.
客…行舟 2025-01-02 04:23:19

一个快速解决方法是执行此操作

abstract case class MyParent(param: Int) {
   println("Form parent : " + param)
}

case class MyChild(override val param: Int) extends MyParent(param) {
   println("Form child : " + param)
}

val c = MyChild(10);

这将导致此结果

>> From parent : 10 
>> From child : 10 

实际上 extends MyParent() 与 Java 中不同。这是一种告诉 MyChild 扩展 MyParent 的方法,并首先调用后者的超级构造函数。

A quick fix for that is to do this

abstract case class MyParent(param: Int) {
   println("Form parent : " + param)
}

case class MyChild(override val param: Int) extends MyParent(param) {
   println("Form child : " + param)
}

val c = MyChild(10);

This will result in this

>> From parent : 10 
>> From child : 10 

Actually the extends MyParent() is not like in Java. This is a way to tell MyChild extends MyParent, and call the super constructor of the latter at first.

_失温 2025-01-02 04:23:19

利润在哪里?

只是缺少一个不太有用的特殊情况。 case class MyChild(param: Int) 中的 param 是一个类成员,也是一个构造函数参数,因此祖先之一已经拥有一个(非抽象)param 成员,它必须被覆盖。 Scala 在覆盖其他地方时需要 override 关键字,因此这里也需要它。

Where is the profit?

Simply the lack of a not-too-useful special case. param in case class MyChild(param: Int) is a class member as well as a constructor parameter, so one of ancestors already has a (non-abstract) param member, it has to be overridden. And Scala requires override keyword when overriding everywhere else, so it requires it here as well.

油焖大侠 2025-01-02 04:23:19

就我有限的 Scala 知识而言,案例类通常用于不可变的代数数据类型和模式匹配。因此,您可能应该创建一个包含“父”类的类,而不是创建“子类”。

> case class MyParent(param: Int)
defined class MyParent

> case class MyChild(param: Int, parent: MyParent)
defined class MyChild

> def foo(c: MyChild) = c match {
    case MyChild(p, MyParent(p2)) => println("p: " + p + ", p2 " + p2)
  }
foo: (c: MyChild)Unit

> foo(MyChild(3, MyParent(4)))
p: 3, p2 4

As far as my limited Scala knowledge goes, case classes are typically used for immutable algebraic data types and pattern matching. Therefore, instead of creating a "child class", you should probably instead create a class which contains the "parent" class.

> case class MyParent(param: Int)
defined class MyParent

> case class MyChild(param: Int, parent: MyParent)
defined class MyChild

> def foo(c: MyChild) = c match {
    case MyChild(p, MyParent(p2)) => println("p: " + p + ", p2 " + p2)
  }
foo: (c: MyChild)Unit

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