27

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

我假设由于 A 和 B 编译为 (interface,class) 对,因此在编译 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
4

5 回答 5

54

这在 2.8 和 2.11 中对我有用,并且可以让你在 traitAB

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"
}
于 2009-12-03T07:12:46.070 回答
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's 的结果如下(注意使用{}来实例化特征):

scala> (new A {}).hi
A

scala> (new B {}).hi
B

scala> (new C).hi
B
于 2009-12-02T23:11:16.147 回答
4

一个特征将方法添加到混合它的类中。如果两个特征添加相同的方法,则该类最终会得到两个相同的方法,这当然不可能发生。

但是,如果该方法在 trait 中是私有的,则不会引起问题。如果您希望这些方法相互堆叠,您可以定义一个基本特征,然后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

但是,如果您真的希望每个 trait 有两个单独的方法,那么您将需要compose而不是inherit

于 2009-12-02T23:27:12.517 回答
1

这就是钻石问题hi应该继承哪个方法,来自 A 的方法,还是来​​自 B 的方法?您可以按照 Don 的建议,通过使用共同的基本特征来解决此问题。

于 2009-12-02T23:24:17.420 回答
0

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

class somethingToTest {
  object AImpl extends ATrait 
  object BImpl extends BTrait

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

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

于 2014-09-08T14:48:50.643 回答