2016-07-13 8 views
1

ich die folgende Fallklasse habenFall Klasse Gleichheit für Arrays

case class Something(val input : Array[Int], val output : Array[Int] = null, val remainder : Array[Int] = null, val next : Something = null) { 
    override def equals(thatGeneric: scala.Any): Boolean = { 
    if(!thatGeneric.isInstanceOf[Something]) 
     return false 

    val that = thatGeneric.asInstanceOf[Something] 

    val thisInput = if(this.input == null) null else this.input.deep 
    val thatInput = if(that.input == null) null else that.input.deep 

    val thisOutput = if(this.output == null) null else this.output.deep 
    val thatOutput = if(that.output == null) null else that.output.deep 

    val thisRemainder = if(this.remainder == null) null else this.remainder.deep 
    val thatRemainder = if(that.remainder == null) null else that.remainder.deep 

    return (thisInput,thisOutput,thisRemainder,this.next) == (thatInput,thatOutput,thatRemainder,that.next) 
    } 

    /** 
    * TODO fix hashcode in case I want to use this in collection 
    * @return 
    */ 
    override def hashCode(): Int = super.hashCode() 
} 

Ich weiß, dass Fall Klassen sollen Ihre equals und hashCode Methoden für Sie erstellt haben, aber für Arrays da == nicht gelingt, dann denke ich, Deshalb funktioniert es nicht für meine Fallklasse.

Gibt es eine bessere Möglichkeit, meine equals- und hashCode-Methoden nicht manuell für meine Fallklasse schreiben zu müssen?

Anmerkung: Ich auch willkommen Beratung darüber, warum/wie mein Strom verbessern Methode equals

Edit: Sie im Allgemeinen die Hinweise über meine Verwendung von Fallklasse zu schätzen wissen, aber meine Frage war im Grunde: Angenommen, Sie das Bedürfnis haben von einem Array in Ihrer Fall-Klasse, wie vermeiden Sie, Ihre eigenen equals und hashCode zu rollen. (Wenn die Antwort ist, dass es unmöglich ist und ich brauche eine Liste, dann ist das die Antwort, nur nicht sicher, dass das der Fall ist.)

+1

Gibt es einen Grund, warum Sie ein 'Array' und nicht eine' List' verwenden möchten? Eine Fallklasse soll traditionell eine unveränderbare Datenstruktur enthalten. –

Antwort

1

Es scheint ein paar Dinge mit dieser Klassendefinition falsch zu sein. Die Verwendung von null s, var s und Array s.

Wie @ m-z erwähnt, sollen Fallklassen als "Daten" -Klassen verwendet werden. Daten, die unveränderbar sein sollten. Wenn Sie nicht Ihre eigenen equals und hashCode rollen müssen, dann sollten Sie die Implementierung überdenken.

Hinweis: Sie sind sich nicht sicher, wofür Sie diese Klasse verwenden möchten, aber möglicherweise gibt es ein Entwurfsmuster, das wahrscheinlich Ihren Anforderungen entspricht und der tatsächlichen Verwendung von Fallklassen entspricht.

+0

Eigentlich ist es unveränderlich, ich hatte es ursprünglich als 'Var's, aber sie können' Val' kein Problem sein. Nicht sicher, was Sie mit dem Problem mit 'Nullen' und' Array's zwar meinen. Können Sie erklären? –

+0

Sie könnten ein 'val' verwenden, aber das Array selbst ist immer noch veränderbar. Anscheinend wollen Sie, dass der ** Inhalt ** des Arrays bei der Berechnung des Hashcodes berücksichtigt wird, aber hier liegt das Problem: Dieser Inhalt kann sich ändern, was den Hashcode ändern und den Vertrag der 'hashCode' Methode ("Immer wenn es während der Ausführung einer Java-Anwendung mehrmals auf demselben Objekt aufgerufen wird, muss die Methode hashCode konsistent die gleiche Ganzzahl zurückgeben", siehe https://docs.oracle.com/javase/7/docs/api/ java/util/Objects.html # hashCode (java.lang.Object)). –

+0

@ RégisJean-Gilles es geht nicht darum, einen veränderlichen Typ als Argumente für Ihre Fallklasse zu verwenden. Zum Beispiel können Sie 'mutable.Seq' verwenden und Fallklassen mit demselben Inhalt wären immer noch gleich. Es ist eine Frage, wie Gleichheit für 'Array' und' Iterator' implementiert wird, was referentielle Gleichheit ist. Siehe http://stackoverflow.com/q/3737711/552902 – JRomero

2

Array ist in der Tat leichter, aber leider nicht viel von (scala reimplementieren nicht die meisten Methoden für das Array, so dass sie am Ende die Generika (sucky) scala Sammlung anwendungstechnischen Eigenschaften teilen.

Wie solange Sie auf Verwendung von Arrays festgelegt sind, werden Sie Ihre eigene equals implementieren müssen, nicht viel, dass Sie das tun können, aber man kann es so aussehen machen schönere,:

def eq[T](a: Array[T], b: Array[T]) = Option(a.toSeq) == Option(b.toSeq) 
def equals(that: Something) = 
    eq(input, that.input) && 
    eq(output, that.output) && 
    eq(remainder, that.remainder) && 
    next == that.next 

Sie berücksichtigen sollten, machen Wie auch immer, null wird keine Punkte in sca erzielen la.

Auch, wieder wie alle anderen gesagt, überdenken Sie Ihre Klasse als Fall-Klasse: Der ganze Sinn der Verwendung von Fall-Klassen ist equals und hashCode (und einige andere Sachen) kostenlos. Wenn Sie das alles trotzdem erneut implementieren möchten, deklarieren Sie es als Fallklasse, wenn es nur verwirrend ist und keinen Nutzen bringt.