Всегда ли "==" в Ruby равнозначно равенству?
Извините, если дублируется (я не нашел его)
Это только для того, чтобы подтвердить, что оператор Руби ==
всегда выполняет сравнение на равенство Т.е.
a == b
сравнивает значение a со значением b, вместо того, чтобы, как в Java, указывать, указывают ли они на один и тот же объект в памяти (для этого, в Ruby, следует использовать a.object_id == b.object_id
).
Таким образом, в результате безопасно сравнивать строковые значения с == в Ruby (хотя это небезопасно в Java)
Спасибо
Редактировать:
Вопрос заключается в поведении по умолчанию == для любого объекта Ruby, так как это может ввести в заблуждение программистов на Java-C-C++, предполагая, что == b сравнивает сами ссылки, а не содержимое ссылок.
В любом случае, вы можете проверить этот код, используя строки
one="hello"
two="he"
two << "llo"
if one == two
puts "surprise: comparing values, not like in Java"
end
if not one.object_id == two.object_id
puts "obvious: do this to compare references"
end
Изменить 2.
Итак, в Ruby, сравнение
a == b
проверяет значения a и b
но, назначение
a = b
не копирует значения, но заставляет a и b указывать на один и тот же объект!
продолжая предыдущий код
puts one.object_id
puts two.object_id
puts " and now "
one = two
puts one.object_id
puts two.object_id
3 ответа
В рубине ==
может быть перегружен, поэтому он может делать все, что хочет разработчик класса, который вы сравниваете. В этом отношении это очень похоже на Java equals()
метод.
Конвенция для ==
сделать сравнение значений, и большинство классов следуют этому соглашению, String
включен. Итак, вы правы, используя ==
для сравнения строк сделаем ожидаемую вещь.
Конвенция для equal?
сделать сравнение ссылок, так что ваш тест a.object_id == b.object_id
также может быть написано a.equal?(b)
, (The equal?
метод может быть определен, чтобы сделать что-то нестандартное, но опять же, так может object_id
!)
(Примечание: когда вы сравниваете строки в Ruby, вам часто следовало бы вместо этого использовать символы.)
С http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/.
Код:
class MyObject
end
object1 = MyObject.new
object2 = object1
object3 = MyObject.new
puts "Object 1 is == to object 2: #{object1 == object2}"
puts "Object 1 is eql? to object 2: #{object1.eql? object2}"
puts "Object 1 is equal? to object 2: #{object1.equal? object2}"
puts "Object 1 is == to object 3: #{object1 == object3}"
puts "Object 1 is eql? to object 3: #{object1.eql? object3}"
puts "Object 1 is equal? to object 3: #{object1.equal? object3}"
Выход:
Object 1 is == to object 2: true
Object 1 is eql? to object 2: true
Object 1 is equal? to object 2: true
Object 1 is == to object 3: false
Object 1 is eql? to object 3: false
Object 1 is equal? to object 3: false
Редактировать - Дополнительный вывод:
irb(main):001:0> class MyObject
irb(main):002:1> end
=> nil
irb(main):003:0> object1 = MyObject.new
=> #<MyObject:0x281bc08>
irb(main):006:0> object1.respond_to?( '=='.to_sym )
=> true
irb(main):007:0> object1.respond_to?( 'eql?'.to_sym )
=> true
irb(main):013:0> MyObject.superclass
=> Object
Согласно "Языку программирования Ruby" (Flanagan & Matsumoto), раздел 4.6.7, стр. 106.
== это оператор равенства. Он определяет, равны ли два значения, согласно определению левого операнда "равно".
И в 3.8.3 стр. 74:
Каждый объект имеет идентификатор объекта Fixnum, который вы можете получить с помощью метода object_id. Значение, возвращаемое этим методом, является постоянным и уникальным для времени жизни объекта.
Таким образом, это работает противоположно Java (удивительно для меня).