我是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继承冲突成员:String类型的特征T2中的值f1和String类型的特征T3中的变量f1(注意:这可以通过在类C2中声明覆盖来解决 . )类C2使用T3 {}扩展T2
那么如果C2扩展具有相同字段名称的特征,应该改变什么呢?谢谢您的帮助 .
3 回答
您可以手动解决歧义:
要么
如果是的话,编译器可以通过线性化自动完成
Conflicting fields in Scala Traits
接受的答案是正确的,但请记住,建议的模式很奇怪,可能导致很难理解非平凡案例中的错误 . 根据我的经验,重写非抽象
vals
只会让你遇到麻烦 .问题是初始化代码是定义的类/特征的构造函数的一部分 . 这意味着在创建
C2
的实例时将执行初始化T2.f1
和T3.f1
的代码:如果初始化代码有任何重要的副作用,这可能会导致难以追踪的错误!它还有一个缺点,就是强迫你在
C2
中重复一些T3
的代码 .如果您不是绝对需要
T2.f1
和T3.f1
为vals
,那么最好使用defs
来避免抽象vals
中的初始化代码:如果你真的需要
f1
成为一个val,例如如果您需要一个稳定的值来在模式匹配语句中使用它,您可以使用以下内容:最后一个解决方案有点冗长,但它通过避免覆盖非抽象
val
来完全绕过问题 .建议的例子是正确的,但尽量避免循环依赖,它也可能导致一些严重的问题 .
看到这里的问题是你在两个特征中都有相同的字段,编译器无法解析你将使用哪个特性的属性 . 因此,您可以通过使其明确编译器来解决问题 .