为什么我会收到以下错误?如何解决它?
我假设由于A和B编译为(接口,类)对,因此在编译C时选择正确的静态方法调用是一个问题。我希望优先级按顺序排列。
scala> trait A { def hi = println("A") }
defined trait A
scala> trait B { def hi = println("B") }
defined trait B
scala> class C extends B with A
<console>:6: error: error overriding method hi in trait B of type => Unit;
method hi in trait A of type => Unit needs `override' modifier
class C extends B with A
scala> trait A { override def hi = println("A") }
<console>:4: error: method hi overrides nothing
trait A {override def hi = println("A")}
请注意,在Ruby中,这很有效:
>> module B; def hi; puts 'B'; end; end
=> nil
>> module A; def hi; puts 'A'; end; end
=> nil
>> class C; include A; include B; end
=> C
>> c = C.new
=> #<C:0xb7c51068>
>> c.hi
B
=> nil
答案 0 :(得分:51)
这适用于我在2.8和2.11中,并且允许您在特征A
或B
中非侵入性:
trait A { def hi = println("A") }
trait B { def hi = println("B") }
class C extends A with B {
override def hi = super[B].hi
def howdy = super[A].hi // if you still want A#hi available
}
object App extends Application {
(new C).hi // prints "B"
}
答案 1 :(得分:12)
您可以使用共同的基本特征,例如Base
,如下所示:
trait Base {def hi: Unit}
trait A extends Base {override def hi = println("A")}
trait B extends Base {override def hi = println("B")}
class C extends A with B
对于类型层次结构,调用hi
的结果如下(注意使用{}
来实例化特征):
scala> (new A {}).hi
A
scala> (new B {}).hi
B
scala> (new C).hi
B
答案 2 :(得分:4)
一个特征为混合它的类添加了方法。如果两个特征添加了相同的方法,那么该类最终会有两个相同的方法,当然,这些方法不会发生。
但是,如果该方法在特征中是私有的,则不会导致问题。如果您希望方法相互堆叠,您可以定义基本特征,然后在继承特征上定义abstract override
。但是,它需要一个类来定义方法。这是一个例子:
scala> trait Hi { def hi: Unit }
defined trait Hi
scala> trait A extends Hi { abstract override def hi = { println("A"); super.hi } }
defined trait A
scala> trait B extends Hi { abstract override def hi = { println("B"); super.hi } }
defined trait B
scala> class NoHi extends Hi { def hi = () }
defined class NoHi
scala> class C extends NoHi with B with A
defined class C
scala> new C().hi
A
B
但是,如果你真的想从每个特征中获得两个独立的方法,那么你需要撰写而不是继承。
答案 3 :(得分:1)
这是diamond problem。应该继承哪种方法hi
,A中的方法还是B中的方法?你可以通过使用共同的基本特征来解决这个问题。
答案 4 :(得分:0)
我有同样的问题而且我不想创建一个中间特征,因为我可以使用相同的方法获得4,5甚至6个特征,因为它是包含CRUD操作的特征(查找,创建) ...)。此外,我需要将这些特性一起用于测试目的,我总是尽量避免修改项目的结构,只是为了让我的测试更容易。 所以我只是在不同的对象中实现了这些特征:
class somethingToTest {
object AImpl extends ATrait
object BImpl extends BTrait
val a = AImpl.methodDuplicated()
val b = BImpl.methodDuplicated()
}
这可能不是使用特征的最聪明的方法,但它不需要对项目代码进行任何更改,它只意味着在测试中有更多的代码。