为什么 Struct/Class 实例的相等性检查不同?
Why equality check for instance of Struct/Class are different?
我不明白结构和 class 相等检查之间的区别。由于 Struct 和 Class 都从内核获取它们的#hash,但它们的行为似乎不同。
我知道 instance.hash 会为每个 class 实例产生不同的结果。与 Class 个实例 [Foo、Object、Kernel、BasicObject] 相比,Struct 实例具有不同的祖先 [Customer、Struct、Enumerable、Object、Kernel、BasicObject]。真正导致每个 Class 实例具有与其他
不同的哈希值的真正原因
Customer = Struct.new(:name, :phone, :address) do
end
class Foo
def initialize(the_name, phone, address)
@name = the_name
@phone = phone
@address = address
end
end
str_a = Customer.new('bond', 'ring', 'address')
str_b = Customer.new('bond', 'ring', 'address')
foo_a = Foo.new('bond', 'ring', 'address')
foo_b = Foo.new('bond', 'ring', 'address')
p str_a == str_b #true
p foo_a == foo_b #false
p str_a.hash # 4473040617195177332
p str_b.hash # 4473040617195177332
p foo_a.hash # -3118151143418428190
p foo_b.hash # -1042397847400824657
p str_a.method(:hash).owner #Kernel
p foo_a.method(:hash).owner #Kernel
Struct 和 Class 都在其 hash_number 生成中使用内核。为什么 Class 的不同实例会产生不同的哈希值,而 Struct 实例会产生相同的哈希值?
我相信您正在寻找的答案可以在 Struct documentation
中找到
Equality—Returns true if other has the same struct subclass
and has equal member values (according to Object#==).
您的示例 str_a
和 str_b
具有相同的成员值,并且它们具有相同的子类 (Customer
),因此与 ==
相比它们是相等的
对比一下 Object documentation
Equality — At the Object level, == returns true only if
obj and other are the same object. Typically, this method is
overridden in descendant classes to provide class-specific meaning.
在您的示例中,foo_a
和 foo_b
不是同一个对象(因为它们不是同一个实例)
如果您正在寻找 为什么 这些不同,我并没有真正回答这个问题。只是该行为符合文档的预期。他们实际上没有相同的 ID:
pry >> Bar = Struct.new(:name) do; end
=> Bar < Struct
pry >> x = Bar.new
=> #<Struct:Bar:0x7f8ebca47610
name = nil
pry >> y = Bar.new
=> #<Struct:Bar:0x7f8ebca14058
name = nil
pry >> x.name = "foo"
=> "foo"
pry >> y.name = "foo"
=> "foo"
pry >> x
=> #<Struct:Bar:0x7f8ebca47610
name = "foo"
pry >> y
=> #<Struct:Bar:0x7f8ebca14058
name = "foo"
但是,您会注意到比较是基于属性,而不是对象 ID:
pry >> x == y
=> true
即使对象 ID 不同:
pry >> x.__id__
=> 70125513489160
pry >> y.__id__
=> 70125513383980
我不明白结构和 class 相等检查之间的区别。由于 Struct 和 Class 都从内核获取它们的#hash,但它们的行为似乎不同。
我知道 instance.hash 会为每个 class 实例产生不同的结果。与 Class 个实例 [Foo、Object、Kernel、BasicObject] 相比,Struct 实例具有不同的祖先 [Customer、Struct、Enumerable、Object、Kernel、BasicObject]。真正导致每个 Class 实例具有与其他
不同的哈希值的真正原因Customer = Struct.new(:name, :phone, :address) do
end
class Foo
def initialize(the_name, phone, address)
@name = the_name
@phone = phone
@address = address
end
end
str_a = Customer.new('bond', 'ring', 'address')
str_b = Customer.new('bond', 'ring', 'address')
foo_a = Foo.new('bond', 'ring', 'address')
foo_b = Foo.new('bond', 'ring', 'address')
p str_a == str_b #true
p foo_a == foo_b #false
p str_a.hash # 4473040617195177332
p str_b.hash # 4473040617195177332
p foo_a.hash # -3118151143418428190
p foo_b.hash # -1042397847400824657
p str_a.method(:hash).owner #Kernel
p foo_a.method(:hash).owner #Kernel
Struct 和 Class 都在其 hash_number 生成中使用内核。为什么 Class 的不同实例会产生不同的哈希值,而 Struct 实例会产生相同的哈希值?
我相信您正在寻找的答案可以在 Struct documentation
中找到Equality—Returns true if other has the same struct subclass
and has equal member values (according to Object#==).
您的示例 str_a
和 str_b
具有相同的成员值,并且它们具有相同的子类 (Customer
),因此与 ==
相比它们是相等的
对比一下 Object documentation
Equality — At the Object level, == returns true only if
obj and other are the same object. Typically, this method is
overridden in descendant classes to provide class-specific meaning.
在您的示例中,foo_a
和 foo_b
不是同一个对象(因为它们不是同一个实例)
如果您正在寻找 为什么 这些不同,我并没有真正回答这个问题。只是该行为符合文档的预期。他们实际上没有相同的 ID:
pry >> Bar = Struct.new(:name) do; end
=> Bar < Struct
pry >> x = Bar.new
=> #<Struct:Bar:0x7f8ebca47610
name = nil
pry >> y = Bar.new
=> #<Struct:Bar:0x7f8ebca14058
name = nil
pry >> x.name = "foo"
=> "foo"
pry >> y.name = "foo"
=> "foo"
pry >> x
=> #<Struct:Bar:0x7f8ebca47610
name = "foo"
pry >> y
=> #<Struct:Bar:0x7f8ebca14058
name = "foo"
但是,您会注意到比较是基于属性,而不是对象 ID:
pry >> x == y
=> true
即使对象 ID 不同:
pry >> x.__id__
=> 70125513489160
pry >> y.__id__
=> 70125513383980