Os novatos terão problemas com métodos de igualdade :
- a == b : verifica se a e b são iguais. Isso é o mais útil.
- a.eql? b : também verifica se a e b são iguais, mas às vezes é mais estrito (pode verificar se a e b têm o mesmo tipo, por exemplo). É usado principalmente em Hashes.
- a.equal? b : verifica se aeb são o mesmo objeto (verificação de identidade).
- a === b : usado em declarações case (eu li como " a corresponde a b ").
Esses exemplos devem esclarecer os primeiros 3 métodos:
a = b = "joe"
a==b # true
a.eql? b # true
a.equal? b # true (a.object_id == b.object_id)
a = "joe"
b = "joe"
a==b # true
a.eql? b # true
a.equal? b # false (a.object_id != b.object_id)
a = 1
b = 1.0
a==b # true
a.eql? b # false (a.class != b.class)
a.equal? b # false
Observe que == , eql? e igual? deve ser sempre simétrico: se a == b então b == a.
Observe também que == e eql? são ambos implementados na classe Object como aliases para iguais? , então se você criar uma nova classe e quiser == e eql? para significar algo diferente de identidade simples, então você precisa substituir os dois. Por exemplo:
class Person
attr_reader name
def == (rhs)
rhs.name == self.name # compare person by their name
end
def eql? (rhs)
self == rhs
end
# never override the equal? method!
end
O método === se comporta de maneira diferente. Em primeiro lugar, não é simétrico (a === b não implica que b === a). Como eu disse, você pode ler a === b como "a corresponde a b". Aqui estão alguns exemplos:
# === is usually simply an alias for ==
"joe" === "joe" # true
"joe" === "bob" # false
# but ranges match any value they include
(1..10) === 5 # true
(1..10) === 19 # false
(1..10) === (1..10) # false (the range does not include itself)
# arrays just match equal arrays, but they do not match included values!
[1,2,3] === [1,2,3] # true
[1,2,3] === 2 # false
# classes match their instances and instances of derived classes
String === "joe" # true
String === 1.5 # false (1.5 is not a String)
String === String # false (the String class is not itself a String)
A declaração de caso é baseada no método === :
case a
when "joe": puts "1"
when 1.0 : puts "2"
when (1..10), (15..20): puts "3"
else puts "4"
end
é equivalente a isto:
if "joe" === a
puts "1"
elsif 1.0 === a
puts "2"
elsif (1..10) === a || (15..20) === a
puts "3"
else
puts "4"
end
Se você definir uma nova classe cujas instâncias representam algum tipo de contêiner ou intervalo (se tiver algo como um método include? Ou match? ), Pode ser útil substituir o método === desta forma:
class Subnet
[...]
def include? (ip_address_or_subnet)
[...]
end
def === (rhs)
self.include? rhs
end
end
case destination_ip
when white_listed_subnet: puts "the ip belongs to the white-listed subnet"
when black_listed_subnet: puts "the ip belongs to the black-listed subnet"
[...]
end