为什么类不能使用相同签名的方法扩展特征?

问题描述 投票:27回答:5

为什么我会收到以下错误?如何解决它?

我假设由于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
scala override traits
5个回答
52
投票

这适用于2.8和2.11,并且允许你在特征AB中非侵入性:

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

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

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

但是,如果你真的想从每个特征中获得两个独立的方法,那么你需要编写而不是继承。


1
投票

这是diamond problemhi应该继承哪种方法,一种来自A,还是一种来自B?你可以通过使用共同的基本特征来解决这个问题。


0
投票

我有同样的问题,我不喜欢创建一个中间特征,因为我可以使用相同的方法有4,5甚至6个特征,因为它是包含CRUD操作的特征(查找,创建...)。此外,我需要将这些特性一起用于测试目的,我总是尽量避免修改项目的结构,只是为了让我的测试更容易。所以我只是在不同的对象中实现了这些特征:

class somethingToTest {
  object AImpl extends ATrait 
  object BImpl extends BTrait

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

它可能不是使用特征的最聪明的方法,但它不需要对项目代码进行任何更改,它只意味着在测试中有更多的代码。

© www.soinside.com 2019 - 2024. All rights reserved.