Frage

Warum erhalte ich die Fehlermeldung unten? Wie es zu umgehen?

Ich nahm an, da A und B (Schnittstelle, Klasse) Paare zusammenstellen, es ist eine Frage des richtigen statischen Methodenaufrufes der Wahl zu implementieren, wenn C. kompilieren würde ich die Priorität erwartet nach Ordnung zu sein.

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

Beachten Sie, dass in Ruby das funktioniert gut:

>> 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
War es hilfreich?

Lösung

Dies funktioniert für mich in 2.8 und 2.11 und Sie erlauben würde, nicht-intrusive in Zügen A oder B zu sein:

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

Andere Tipps

Sie könnten eine gemeinsame Basis Merkmal verwenden, sagen Base, wie folgt:

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

Mit der Typenhierarchie das Ergebnis des Aufrufs hi der ist wie folgt (beachten Sie die Verwendung von {} die Züge zu instanziiert):

scala> (new A {}).hi
A

scala> (new B {}).hi
B

scala> (new C).hi
B

Ein Merkmal fügt Methoden der Klasse, die sie in mischt. Wenn zwei Züge die gleiche Methode fügt, würde die Klasse nach oben mit zwei identischen Methoden beenden, was natürlich kann nicht passieren.

Wenn die Methode in dem Merkmale privat ist, wird es jedoch nicht dazu führen Problem. Und wenn Sie die Methoden übereinander stapeln mögen, können Sie eine Basis Merkmal definieren und dann auf den Vererbungseigenschaften abstract override. Es erfordert eine Klasse, die Methode zu definieren, jedoch. Hier ist ein Beispiel dafür:

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

Wenn Sie jedoch wirklich zwei getrennte Methoden wollen aus jedem Zug, dann werden Sie brauchen, um compose statt inherit .

Dies ist der Diamant Problem . Welche Methode hi soll, die man von A vererbt werden, oder das von B? Sie können dieses Problem umgehen, wie Don vorgeschlagen, durch eine gemeinsame Basis Merkmal verwendet wird.

Ich hatte das gleiche Problem, und ich wusste nicht, wie ein Vermittler Merkmal zu schaffen zu haben, weil ich 4,5 oder sogar 6 Züge mit den gleichen Methoden haben kann, weil sie Merkmale ist enthalten CRUD-Operationen (finden, erstellen .. .). Außerdem brauchte ich zusammen jene Eigenschaft zu verwenden, nur zu Testzwecken und ich versuche immer, so weit wie möglich zu vermeiden, dass die Struktur meines Projektes zu ändern, dass nur meinen Test zu erleichtern. So implementiert ich einfach diese Eigenschaften in verschiedenen Objekten:

class somethingToTest {
  object AImpl extends ATrait 
  object BImpl extends BTrait

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

Es ist wahrscheinlich nicht die clevere Art Züge zu benutzen, aber es erfordert keine Änderung im Code des Projektes, es bedeutet nur ein bisschen mehr Code in den Tests zu haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top