如果我分别创建两个具有相同内容的String实例,则它们是相同的。默认情况下,自定义类不是这种情况(参见下面的示例)。
如果我有自己的班级(下面是Test
)并且我有一个变量(下面是@v
),这是唯一的,即。具有相同Test
的两个@v
实例应该被视为相同,那么我将如何告诉Ruby这是这种情况呢?
考虑这个例子:
class Test
def initialize(v)
@v = v
end
end
a = {Test.new('a') => 1, Test.new('b') => 2}
a.delete(Test.new('a'))
p a
# # Desired output:
# => {#<Test:0x100124ef8 @v="b">=>2}
答案 0 :(得分:1)
您需要定义一个==
方法,用于定义相等对您的类的含义。在这种情况下,您需要:
class Test
def initialize(v)
@v = v
end
def ==(other)
@v == other.instance_variable_get(:@v)
end
end
答案 1 :(得分:1)
您正在使用类Test
的对象作为哈希的键。为了使其正常运行(以及a.delete
),您需要在Test中定义两个方法:Test#hash
和Test#eql?
来自:http://ruby-doc.org/core/classes/Hash.html
哈希使用key.eql?测试密钥 平等。如果您需要使用实例 你自己的类作为哈希中的键, 建议您同时定义它们 eql?和哈希方法。哈希 方法必须具有该属性 a.eql?(b)暗示a.hash == b.hash。
答案 2 :(得分:1)
我发现了一种不同的解决方法,通过跟踪内部测试的所有实例,我可以返回预制实例,而不是创建一个新实例并告诉ruby它们是等效的:
class Test
def self.new(v)
begin
return @@instances[v] if @@instances[v]
rescue
end
new_test = self.allocate
new_test.instance_variable_set(:@v,v)
(@@instances ||= {})[v] = new_test
end
end
现在Test.new('a') == Test.new('a')
和 Test.new('a') === Test.new('a')
:)
答案 3 :(得分:1)
大多数情况下,您需要具有可比性和/或可散列性的对象由成员变量组成,这些变量可以是基元(整数,字符串等),也可以是可比较/可清除的。在这些情况下,这个模块:
module Hashable
include Comparable
def ==(other)
other.is_a?(self.class) && other.send(:parts) == parts
end
alias_method :eql?, :==
def hash
parts.hash
end
end
可以简单地包含在您的班级中,以处理所有繁忙的工作。您所要做的就是定义一个“parts”方法,该方法返回构成对象状态的所有值:
class Foo
include Hashable
def initialize(a, b)
@a = a
@b = b
end
private
def parts
[@a, @b]
end
end
以这种方式构建的对象具有可比性(它们具有&lt;,&lt; =,==,&gt; =,&gt;,!=和equ?)并且它们可以是哈希键。