8 Stimmen

Umbenennen und Überschreiben der Methode equals in der Fallklasse

Ich möchte ein Merkmal mit dem Namen Ext definieren, das die vorhandene Methode equals in equalsByAttributes umbenennt und gleichzeitig eine neue equals Methode definiert. Das Merkmal wird verwendet, um Fallklassen zu erweitern. Meine aktuelle Lösung sieht irgendwie heimtückisch aus:

case class A(id: Int) extends Ext

trait Ext { p: Product =>
    // neue Implementierung
    override def equals(obj: Any) = obj match {
        case that: AnyRef => this eq that
        case _ => false
    }

    // Neuimplementierung der alten equals-Implementierung
    def equalsByAttributes(obj: Any) = obj match {
        case that: Product =>
            if (this.getClass.isAssignableFrom(that.getClass) || that.getClass.isAssignableFrom(this.getClass))
                p.productIterator.toList == that.productIterator.toList
            else
                false
        case _ => false
    }
}

Ich frage mich, ob es eine direkte Möglichkeit gibt, auf die equals-Methode von A in equalsByAttributes zu verweisen, um die Neuimplementierung dieser Methode zu vermeiden?

Bearbeiten 2012-07-12

Da es eine Lösung für das Referenzieren von Superimplementierungen mit super.METHOD_NAME gibt, dachte ich, es müsse eine ähnliche Syntax wie overridden.METHOD_NAME geben, um spezifische Implementierungen in der Basisklasse/dem Basistrait abzurufen, die vom Trait erweitert werden soll. Meine Ext-Trait würde dann so aussehen:

trait Ext { p: Product =>
    override def equals(obj: Any) = ...

    def equalsByAttributes(obj: Any) = overridden.equals(obj)
}

13voto

Daniel C. Sobral Punkte 290004

Ändern Sie keine Gleichheitszeichen bei Case-Klassen. Wenn Sie dies tun müssen, machen Sie Ihre Klassen nicht zu Case-Klassen. Das Ändern von Case-Klassenmethoden führt dazu, dass der Code unerwartet verhält (das heißt, nicht wie Case-Klassen), was die Wartungskosten erhöht, alles bricht, was davon ausgeht, dass Case-Klassen wie Case-Klassen funktionieren, das Leben der Menschen elend macht und dazu führt, dass viele Programmierer Sie hassen.

Mit anderen Worten, es lohnt sich nicht. Machen Sie das nicht.

7voto

Malte Schwerhoff Punkte 12466

Der Compiler wird kein equals (und hashCode, beziehungsweise) für case classes generieren, die bereits über ein equals verfügen, d.h. die eines erben oder selbst deklarieren. Lesen Sie mehr darüber in diesem Blog-Eintrag. Meines Wissens nach ist das einzige, was Sie tun können, die strukturelle Gleichheit zu implementieren, indem Sie productIterator verwenden, das vom Product Trait bereitgestellt wird, das von case classes erweitert wird, genau wie Sie es bei equalsByAttributes getan haben.

0voto

pedrofurla Punkte 12743

Dieser Code wird die Methodeimplementierung aus dem Ext trait verwenden:

case class A(id: Int) extends Ext { 
  def someEqual(x:Any) = { 
    super[Ext].equalsByAttributes(x) 
  } 
}

Das super[X] hier wird verwendet, um auf eines der Traits zu verweisen, die diese Klasse erweitert. Dies beantwortet Ihre zweite Frage.

Für Ihre erste Frage:

trait Ext { p: A => def eql(x:Any) = p.equals(x) }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X