2012-03-24 2 views
7

Sto leggendo la programmazione in Scala. Dice:Scala: Fa == l'impostazione predefinita è uguale a?

È possibile ridefinire il comportamento di == per i nuovi tipi sovrascrivendo il metodo equals, che è sempre ereditato dalla classe Any. L'ereditato equals, che ha effetto se non sovrascritto, è l'identità dell'oggetto, come nel caso di Java. Pertanto, equals (e con esso, ==) è lo stesso predefinito di eq, ma è possibile modificarne il comportamento sostituendo il metodo equals nelle classi definite. Non è possibile sovrascrivere direttamente ==, poiché è definito come metodo finale nella classe Any. Cioè, Scala tratta == come se è stata definita come segue in classe Any:

final def == (that: Any): Boolean = 
    if (null eq this) (null eq that) else (this equals that) 

Ma questo non è strambate con quello che sto vedendo in scala 2.9.1, in cui sembra che:

  • == non sembra default equals
  • posso ignorare == direttamente (senza lamentarsi dal compilatore, non override necessario).

Così sembra a me come sia:

  • sto facendo male - this definition of Rational

    % scala                 
    Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29). 
    Type in expressions to have them evaluated. 
    Type :help for more information. 
    
    scala> Rational(1) == Rational(1) 
    res0: Boolean = false 
    
    scala> Rational(1) equals Rational(1) 
    res1: Boolean = true 
    
  • o sto leggendo un fuori versione aggiornata del libro, e le cose sono cambiate.

Cosa sta succedendo?

risposta

21

Si sta commettendo un errore molto comprensibile: si sta tentando di scrivere un uguale sicuro al tipo (ad esempio def equals(r: Rational)) anziché un uguale generico (ad esempio override def equals(a: Any)).

Così, invece di assoluta equals --Nota che non è necessario la parola override - si sta creando un altro metodo sovraccaricando i parametri del tipo, e poi dover due uguale metodi, uno che prende Rational e uno che prende Any. Stessa cosa con ==; solo il metodo Any -parameterizzato non può essere sovrascritto.

per ottenere il comportamento coerente con Java (e la libreria Scala), avresti bisogno di riscrivere uguale come qualcosa di simile

override def equals(a: Any) = a match { 
    case r: Rational => numer == r.numer && denom == r.demon 
    case _ => false 
} 
+0

impressionante. Questo mi morde ogni volta che torno in JVM land. Lo imparerò prima o poi. Esiste comunque la possibilità di rilasciare 'a match' e assegnare a' equals' una funzione anonima? 'override def equals: Any => Boolean = {case r: Rational/* ... * /}' non funziona ... – rampion

+2

@rampion - No, devi corrispondere esattamente alla firma del tipo. 'equals: Any => Boolean' significa che restituisce una funzione (cioè un'istanza di una classe' Function1 [Any, Boolean] '). Anche se questo è concettualmente equivalente in un certo senso, non è lo stesso identico metodo, quindi non funzionerà. –