Классы дел и поведение прокси в Scala 2.9

При миграции нашего кода на Scala 2.9 мы обнаружили большие его участки, которые не работали и терпели неудачу. Мы отследили это до классов case, которые расширяют Proxy, не будучи равными. В нашем коде мы не расширяем Proxy напрямую, мы просто расширяем классы в библиотеках, которые расширяют Proxy.

Любая помощь будет принята с благодарностью.

In 2.8

scala> case class Test(a:String) extends Proxy {
     |   def self = a
     | }
defined class Test

scala> 

scala> val label = new Test("bla")
label: Test = bla

scala> println(label == label) // this is TRUE
true

scala> println(label == "bla")
true

In 2.9

scala> case class Test(a:String) extends Proxy {
     |   def self = a
     | }
defined class Test

scala> 

scala> val label = new Test("bla")
label: Test = bla

scala> println(label == label) // this is now FALSE
false

scala> println(label == "bla")
true

Обновить

Я думаю, это может быть ошибка только в Scala 2.9. В противном случае, если у вас есть класс case, который расширяет любой другой класс, вам нужно исследовать иерархию этого базового класса, чтобы убедиться, что он ни в коем случае не расширяет Proxy. Мы не сможем сделать это в нашем коде, мы просто сможем исправить наиболее очевидные ошибки. Если это предполагаемое поведение, предупреждение компилятора является обязательным. Это звучит примерно правильно?

Обновить

Также обсуждается на список рассылки scala.

Обновить

Я зарегистрировал ошибку


person David    schedule 12.07.2011    source источник
comment
Вы в конечном итоге сообщили об этом как об ошибке? (Если да, ссылка?) Документация для Proxy предупреждает вас, что это может привести к тому, что equals не будет симметричным, но не предупреждает вас, что equals может даже не быть рефлексивным ...!   -  person Seth Tisue    schedule 15.07.2011
comment
Сет, я согласен, это может быть только ошибкой. Я обновился по ссылке выше.   -  person David    schedule 15.07.2011
comment
Ошибка была исправлена ​​10 сентября 2011 г.   -  person James Moore    schedule 29.10.2011
comment
Да, но я жду, когда это будет связано с версией Scala, прежде чем праздновать. Это было исправлено некоторое время, но пока нет никаких признаков того, что он будет выпущен.   -  person David    schedule 31.10.2011


Ответы (3)


В 2.9 они изменили метод equals с:

override def equals(that: Any): Boolean = 
  if(that == null) false 
  else that equals self

to

override def equals(that: Any): Boolean = that match {
 case null       => false
 case x: Equals  => (x canEqual self) && (x equals self)
 case x          => (x equals self)
}

x: Equals по какой-то причине не равно self.

Вы можете переопределить метод equals, чтобы исправить это.

person Joe0    schedule 12.07.2011
comment
Я думаю, что самое простое решение - просто изменить класс case на класс для нас. Однако это кажется сломанным или, по крайней мере, изменением поведения, которое должно было быть задокументировано. Спасибо - person David; 13.07.2011
comment
Я думаю, что это, вероятно, ошибка, но этот ответ объясняет, где возникла ошибка, поэтому я ее принимаю. Спасибо, Джо. - person David; 15.07.2011

Это решит вашу проблему

case class Test(a: String) extends Proxy {
   def self = a
   def canEqual(that: Any) = that match {
      case that: String => true
      case _ => false
   }
}
person agilesteel    schedule 12.07.2011
comment
Или, проще говоря, that.isInstanceOf[String]. - person Daniel C. Sobral; 12.07.2011
comment
Также обратите внимание, что это означает, что label == "blah" вернет true. - person Daniel C. Sobral; 12.07.2011
comment
В соответствии с результатами, указанными в вопросе, он вернул истину в 2.8. Я думаю, что целью было воспроизвести поведение 2.8. - person Joe0; 13.07.2011

Так почему бы вам не перезаписать метод equals? Это должно решить проблему.

person Kim Stebel    schedule 12.07.2011
comment
Используя класс case, вы должны получить работающий метод equals. Использование класса case и переопределение метода equals кажется немного безумным, я просто не мог бы использовать класс case, который бы работал. Просто в нашем коде их полно. - person David; 13.07.2011
comment
Конечно, это не идеально, но другого пути я не вижу. - person Kim Stebel; 13.07.2011