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

时间:2009-12-02 21:49:44

标签: scala override traits

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

我假设由于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

5 个答案:

答案 0 :(得分:51)

这适用于我在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"
}

答案 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()
}

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