2012-03-24 21 views
7

Estoy leyendo a través de la Programación en Scala. Dice:Scala: ¿== default es igual a?

Puede volver a definir el comportamiento de == para los nuevos tipos reemplazando el método equals, que siempre se hereda de la clase Any. El equals heredado, que tiene vigencia a menos que se invalide, es la identidad del objeto, como es el caso de Java. Por lo tanto, equals (y con ella, ==) es por defecto el mismo que eq, pero puede cambiar su comportamiento anulando el método equals en las clases que defina. No es posible anular == directamente, ya que se define como un método final en la clase Any. Es decir, Scala trata == como si se define de la siguiente en la clase Any:

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

Pero esto no se trasluchadas con lo que estoy viendo en Scala 2.9.1, donde parece que:

  • == no parece que por defecto a equals
  • puedo anular == directamente (sin denuncia por parte del compilador, sin override es necesario).

Por lo tanto, me parece bien:

  • que estoy haciendo mal - this definition of Rational da

    % 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 estoy leyendo una versión desactualizada de la libro, y las cosas han cambiado.

¿Qué está pasando?

Respuesta

21

Está cometiendo un error muy comprensible: está intentando escribir un valor igual de seguro (es decir, def equals(r: Rational)) en lugar de un igual genérico (es decir, override def equals(a: Any)).

Así que en lugar de primordial equals --Nota que no necesita la palabra clave override - va a crear otro método por la sobrecarga de los parámetros de tipo, y luego tener dos es igual a métodos, uno que tiene Rational y uno que toma Any. Lo mismo con ==; solo el método parametrizado Any no puede anularse.

para obtener el comportamiento consistente con Java (y la biblioteca Scala), que había necesidad de reescribir iguales como algo parecido a

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

impresionante. Esto me muerde cada vez que regreso a JVM. Lo aprenderé tarde o temprano. ¿Hay alguna forma de que pueda soltar el 'a match' y simplemente asignar' equals' a una función anónima? 'override def equals: Any => Boolean = {case r: Rational/* ... * /}' no funciona ... – rampion

+2

@rampion - No, debe coincidir exactamente con la firma del tipo. 'equals: Any => Boolean' significa que devuelve una función (es decir, una instancia de una clase' Function1 [Any, Boolean] '). Aunque esto es conceptualmente equivalente en cierto sentido, no es exactamente el mismo método, por lo que no funcionará. –