Scala: == по умолчанию равно? - PullRequest
7 голосов
/ 24 марта 2012

Я читаю через Программирование в Scala. Это говорит:

Вы можете переопределить поведение == для новых типов, переопределив метод equals, который всегда наследуется от класса Any. Унаследованный equals, который вступает в силу, если не переопределен, является идентификатором объекта, как в случае с Java. Таким образом, equals (и вместе с ним ==) по умолчанию совпадает с eq, но вы можете изменить его поведение, переопределив метод equals в определяемых вами классах. Невозможно переопределить == напрямую, так как он определен как последний метод в классе Any. То есть Scala обрабатывает == так, как если бы он был определен в классе Any следующим образом:

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

Но это не вяжется с тем, что я вижу в scala 2.9.1, где это выглядит так:

  • == не похоже на значение по умолчанию equals
  • Я могу переопределить == напрямую (без жалоб со стороны компилятора, override не требуется).

Так что мне кажется, что либо:

  • Я делаю это неправильно - это определение 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
    
  • или я читаю устаревшую версию книги, и все изменилось.

Что происходит?

1 Ответ

21 голосов
/ 24 марта 2012

Вы делаете очень понятную ошибку - вы пытаетесь написать безопасные по типу равно (то есть def equals(r: Rational)) вместо общих равных (то есть override def equals(a: Any)).

Таким образом, вместо переопределенияequals - обратите внимание, что вам не нужно ключевое слово override! - вы создаете другой метод, перегружая параметры типа, а затем два равны методам, один из которых принимает Rationalи тот, который занимает Any.То же самое с ==;только Any -параметризованный метод не может быть переопределен.

Чтобы согласовать поведение с Java (и библиотекой Scala), вам нужно переписать equals как что-то вроде

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