gpt4 book ai didi

scala - Scala中如何解决冲突成员的继承

转载 作者:行者123 更新时间:2023-12-05 02:16:32 25 4
gpt4 key购买 nike

我是 Scala 初学者。有人告诉我“特征中的字段可以是具体的或抽象的”。

trait T2 {
val f1: String = "T2f1"
}

trait T3 {
val f1: String = "T3f1"
}

class C2 extends T2 with T3{}

object Test2 extends App {
val c2 = new C2
println(c2.f1)
}

当我运行上面的代码时,编译器打印了一些错误信息:

"C2 类继承了冲突的成员: 字符串类型的特征 T2 中的值 f1 和 字符串类型的特征 T3 中的变量 f1(注意:这可以通过在类 C2 中声明覆盖来解决。)C2 类使用 T3{} 扩展 T2"

那么,如果 C2 扩展具有相同字段名称的特征,应该更改什么?感谢您的帮助。

最佳答案

接受的答案是正确的,但请记住,建议的模式很奇怪,可能会导致在非平凡情况下难以理解的错误。根据我的经验,重写非抽象 vals 只会给您带来麻烦

问题在于初始化代码是已定义类/特征的构造函数的一部分。这意味着初始化 T2.f1T3.f1 的代码将在创建 C2 实例时执行:

trait T2 {
val f1: String = {
println("T2")
"T2f1"
}
}

trait T3 {
val f1: String = {
println("T3")
"T3f1"
}
}

class C2 extends T2 with T3 {
override val f1: String = {
println("C2")
"T3f1"
}
}

new C2 // Will print "T2", then "T3", then "C2"

如果初始化代码有任何重要的副作用,这可能会导致难以追踪的错误!它还具有强制您在 C2 中重复某些 T3 代码的缺点。

如果您不是绝对需要 T2.f1T3.f1vals,您最好使用 defs 避免在抽象 vals 中初始化代码:

trait T2 {
def f1: String = "T2f1"
}

trait T3 {
def f1: String = "T3f1"
}

class C2 extends T2 with T3 {
override val f1: String = "C2f1" // You can keep this a def if you like
}

如果你真的需要 f1 是一个 val,例如 如果你需要一个稳定的值来在模式匹配语句中使用它,你可以使用下面的代码:

trait T2 {
val f1: String
protected def computeF1: String = {
println("T2")
"T2f1"
}
}

trait T3 {
val f1: String
protected def computeF1: String = {
println("T3")
"T3f1"
}
}

class C2 extends T2 with T3 {
override val f1: String = computeF1 // You can keep this a def if you like
override protected def computeF1: String = super[T3].computeF1
}

new C2 // Only prints "T3" once

最后一个解决方案有点冗长,但它通过避免覆盖非抽象的 val 来完全绕过这个问题。

关于scala - Scala中如何解决冲突成员的继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49715736/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com