2012-03-24 6 views
7

Je lis la programmation dans Scala. Il dit:Scala: Est-ce que == est égal à?

Vous pouvez redéfinir le comportement de == de nouveaux types en redéfinissant la méthode equals, qui est toujours hérité de la classe Any. Le equals hérité, qui prend effet à moins qu'il ne soit ignoré, est l'identité de l'objet, comme c'est le cas en Java. Par conséquent, equals (et avec lui, ==) est par défaut identique à eq, mais vous pouvez modifier son comportement en remplaçant la méthode equals dans les classes que vous définissez. Il n'est pas possible de remplacer == directement, car il est défini comme une méthode finale dans la classe Any. C'est, Scala traite == comme a été défini comme suit dans la classe Any:

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

Mais cela ne jibe avec ce que je vois dans scala 2.9.1, où il semble que:

  • == ne semble pas par défaut equals
  • Je peux passer outre == directement (sans se plaindre du compilateur, pas override nécessaire).

Il me semble que ce soit:

  • Je le fais mal - this definition of Rational donne

    % 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 
    
  • ou je lis une sortie de version date de la livre, et les choses ont changé.

Que se passe-t-il?

Répondre

21

Vous faites une erreur très compréhensible - vous essayez d'écrire un égal à la valeur de type (c'est-à-dire def equals(r: Rational)) au lieu d'un égal générique (c'est-à-dire override def equals(a: Any)).

Ainsi, au lieu de passer outre equals --note que vous n'avez pas besoin du mot-clé override - vous créez une autre méthode en surchargeant les paramètres de type, puis ayant deux égaux méthodes, celui qui prend Rational et un qui prend Any. Même chose avec ==; seule la méthode paramétrée Any ne peut pas être surchargée.

Pour obtenir le comportement compatible avec Java (et la bibliothèque Scala), vous aurez besoin de réécrire équivaut à quelque chose comme

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

Impressionnant. Cela me mord chaque fois que je retourne à la terre de la JVM. Je l'apprendrai tôt ou tard. Y at-il de toute façon que je peux abandonner la 'une correspondance 'et juste assigner une fonction anonyme' equals'? 'override def est égal à: Any => Boolean = {case r: Rational/* ... * /}' ne fonctionne pas tout à fait ... – rampion

+2

@rampion - Non, vous devez faire correspondre exactement la signature du type. 'equals: Any => Boolean' signifie qu'il renvoie une fonction (c'est-à-dire une instance d'une classe' Function1 [Any, Boolean] '). Même si cela est conceptuellement équivalent dans un certain sens, ce n'est pas exactement la même méthode, donc ça ne marchera pas. –