Могу ли я воспроизвести поведение Скалы для ==? - PullRequest
4 голосов
/ 31 января 2011

В Программировании на Scala я могу прочитать, что оператор == ведет себя так, как если бы он был определен так:

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

Но на самом деле должна существовать магия компилятора, чтобы избежать исключений нулевого указателя, верно? Есть ли способ для меня повторить это поведение с чистым Scala; то есть оператор / метод возвращает одну вещь, если получатель нулевой, и другую, если нет? Я имею в виду фактическую реализацию null eq this.

Полагаю, я могу написать "сутенер" и затем определить метод для класса-оболочки, но есть ли более прямой способ сделать это?

Ответы [ 6 ]

2 голосов
/ 31 января 2011

Кажется, что нет никакого способа сделать это без специального случая нулевого регистра. Java не позволяет вызывать метод, если объект имеет значение null. Это по сравнению с таким языком, как python, где None является подходящим объектом. Я думаю, что лучше всего попытаться игнорировать тот факт, что ноль существует.

Использование неявного для симуляции ==

class Equals2(v:AnyRef){
  def ===(that:AnyRef) =  if(v eq null) {that eq null }else {v equals that}
}
implicit def equals2(v:AnyRef) = new Equals2(v) 

К сожалению, следующее не работает, так как нуль не является подклассом AnyRef

null === "Something"
2 голосов
/ 31 января 2011

Нет никакой магии для нулей, но у scala есть некоторая магия для создания равенства, симметричного для чисел.Хитрость заключается в расширении черты ScalaNumber ...

http://www.scala -lang.org / node / 6387

обновление

Просто чтобы прояснить это немного ... Это означает, что если вы пишете a == b и b происходит от ScalaNumber или (я считаю) является AnyVal, то компилятор будет проверять вместо этогоb == a.

Это не только разрешает ситуацию null, но также значительно облегчает задачу, если вы хотите сравнить примитив с каким-либо другим типом, который можно рассматривать как число, но длякоторый неявное преобразование было бы опрометчиво небезопасным.Этот подход используется, например, с BigInteger.

2 голосов
/ 31 января 2011

«null» - единственный экземпляр черты с именем Null - так что это просто нормальный объект, никакой магии для вызова ==

Вы обязательно должны проверить Option и сделать все возможное, чтобы сохранить нулевые значения в вашем коде:)

2 голосов
/ 31 января 2011

Я так не думаю. Насколько я знаю, магии для нулей нет. (см. Обновление)

Я думаю, что лучшее, что вы можете сделать, - это обернуть любой объект в опцию, чтобы вы могли использовать из него кучу полезных вещей:

implicit def toOption[T](target: T) = Option(target)

val q: String = null
val q1: String = "string"

println(q getOrElse "null") // prints: null
println(q1  getOrElse "null") // prints: string

Обновление

Я нашел этот документ:

http://www.scala -lang.org / апи / 2.7.7 / Скала / Null.html

Согласно этому:

Класс Null вместе с классом Nothing находится в нижней части иерархии типов Scala.

Так что даже null имеет методы, унаследованные от AnyRef, такие как eq, == и т. Д. ... И вы также можете использовать их:

val q: String = null
val q1: String = "string"

println(null eq q) // prints: true
println(null eq q1) // prints: false
1 голос
/ 31 января 2011

null - единственный экземпляр Null и, следовательно, - в Scala - полный объект.

Если вы определяете свою функцию в духе, который вы опубликовали выше в классе Aвсе, что вам нужно сделать, это обеспечить неявное преобразование из Null в A, которое отображает null в некоторый фиктивный экземпляр.

0 голосов
/ 31 января 2011

Вы можете использовать Option.

scala> Option("a")
res0: Option[java.lang.String] = Some(a)

scala> Option(null)
res1: Option[Null] = None
...