为什么类不能使用相同签名的方法扩展特征?
为什么我会收到以下错误?如何解决它?
我假设由于 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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这在 2.8 和 2.11 中适用于我,并且允许您不干扰特征
A
或B
:This works for me in 2.8 and 2.11, and would allow you to be non-intrusive in traits
A
orB
:您可以使用一个通用的基本特征,例如
Base
,如下所示:通过类型层次结构,调用
hi
的结果如下(注意使用{}
来实例化特征):You could use a common base trait, say
Base
, as follows:With the type hierarchy the result of calling
hi
's is as follows (note the use of{}
to instantiate the traits):特征向混合它的类添加方法。如果两个特征添加相同的方法,则该类最终将有两个相同的方法,当然,这是不可能发生的。
但是,如果该方法在特征中是私有的,则不会引起问题。如果您希望这些方法相互堆叠,您可以定义一个基本特征,然后在继承特征上进行
抽象覆盖
。然而,它需要一个类来定义该方法。下面是一个示例:但是,如果您确实希望每个特征有两个单独的方法,那么您需要组合而不是继承。
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:If, however, you truly want two separate methods from each trait, then you'll need to compose instead of inherit.
这是钻石问题。应该继承哪一个方法
hi
,是来自 A 的方法,还是来自 B 的方法?您可以按照 Don 的建议,通过使用共同的基本特征来解决这个问题。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.我遇到了同样的问题,我不喜欢创建一个中间特征,因为我可以使用相同的方法拥有 4,5 个甚至 6 个特征,因为它是包含 CRUD 操作(查找、创建...)的特征。此外,我只需要出于测试目的而将这些特征一起使用,并且我总是尝试尽可能避免修改项目的结构,只是为了使测试更容易。
所以我只是在不同的对象中实现了这些特征:
这可能不是使用特征的最聪明的方法,但它不需要对项目的代码进行任何更改,它只意味着在测试中需要更多的代码。
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 :
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.