English 中文(简体)
Why can t a class extend traits with method of the same signature?
原标题:

Why do I get the error below? How to workaround it?

I assumed that since A and B compile to (interface,class) pairs, it s a matter of choosing the right static method call to implement when compiling C. I would expect the priority to be according to order.

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")}

Note that in Ruby this works well:

>> 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
最佳回答

This works for me in 2.8 and 2.11, and would allow you to be non-intrusive in traits A or 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"
}
问题回答

You could use a common base trait, say Base, as follows:

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

With the type hierarchy the result of calling hi s is as follows (note the use of {} to instantiate the traits):

scala> (new A {}).hi
A

scala> (new B {}).hi
B

scala> (new C).hi
B

A trait adds methods to the class that mixes it in. If two traits adds the same method, the class would end up with two identical methods, which, of course, can t happen.

If the method is private in the trait, however, it won t cause problem. And if you want the methods to stack over each other, you may define a base trait and then abstract override on the inheriting traits. It requires a class to define the method, however. Here is an example of this:

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

If, however, you truly want two separate methods from each trait, then you ll need to compose instead of inherit.

This is the diamond problem. Which method hi should be inherited, the one from A, or the one from B? You can get around this as Don suggested, by using a common base trait.

I had the same problem and I didn t like to have to create an intermediary trait because I can have 4,5 or even 6 traits with the same methods, because it is traits containing CRUD operations (find, create...). Furthermore I needed to use those trait together only for test purpose and I always try to avoid as much as possible to modify the structure of my project only to make my test easier. So I simply implemented those traits in different objects :

class somethingToTest {
  object AImpl extends ATrait 
  object BImpl extends BTrait

  val a = AImpl.methodDuplicated()
  val b = BImpl.methodDuplicated()
}

It is probably not the most clever way to use traits but it doesn t require any change in the project s code, it only implies to have a bit more code in the tests.





相关问题
Is it possible to override a non-virtual method?

Is there any way to override a non-virtual method? or something that gives similar results (other than creating a new method to call the desired method)? I would like to override a method from ...

Is is possible to override a hidden method?

Say I have the following hierarchy: public class MyClass { protected virtual void Method() { ... } } public class MySubClass : MyClass { public new virtual void Method() { ... } } public class ...

C++ : implications of making a method virtual

Should be a newbie question... I have existing code in an existing class, A, that I want to extend in order to override an existing method, A::f(). So now I want to create class B to override f(), ...

Override Events in VB.NET

I would like to shadow/override an event in VB.NET. I do it only because I have to implement in this object an interface, that contains the same event like the base object itself, and I need to keep ...

Count calls to eval

I would like to count the number of calls made to eval in our javascript application. I came up with the following, but it generates errors. These errors are hard to track, and my knowledge of the ...

JavaScript: Overriding alert()

Has anyone got any experience with overriding the alert() function in JavaScript? Which browsers support this? Which browser-versions support this? What are the dangers in overriding the function?

热门标签