我需要创建一个类,如果属性值是相同的,它不会生成一个新的对象id,例如:
结果:
described_class.new (01201201202)
<PixKey:0x00007eff5eab1ff8 @key="01201201202">
如果我用相同的值再次运行它它应该保持相同的对象id
0x00007eff5eab1ff8
与符号
的行为类似测试:
describe '#==' do
let(:cpf) { described_class.new('01201201202') }
it 'verifies the key equality' do
expect(cpf).to eq described_class.new('01201201202')
end
end
运行测试显示错误,因为对象id更改:
expected: #<PixKey:0x00007eff5eab1ff8 @key="01201201202">
got: #<PixKey:0x00007eff5eab2070 @key="01201201202">
类:
class PixKey
def init(key)
@key = key
end
end
其他答案很好,但是它们比需要的更冗长,并且它们使用类变量,我发现这是一个令人困惑的概念,因为它们是如何在不同的类之间共享的。
class PixKey
@instances = {}
def self.new(id)
@instances[id] ||= super(id)
end
def initialize(id)
@key = id
end
end
p PixKey.new(1)
p PixKey.new(2)
p PixKey.new(2)
p PixKey.new(1)
运行测试显示错误,因为对象id更改了
不完全是。它显示一个错误,因为对象不相等。错误消息打印两个对象,包括它们的id。但是对象id并不是导致测试失败的原因。
我需要创建一个类,如果属性值是相同的,它不会生成一个新的对象id
这可能会起作用,但你可能从错误的角度处理问题。在Ruby中,相等并不意味着对象同一性。两个对象可以是相等的而不是相同的对象,例如
a = 'foo'
b = 'foo'
a.object_id == b.object_id
#=> false
a == b
#=> true
不需要修改对象id来让测试通过。你只需要实现一个自定义的==
方法,例如:
class PixKey
attr_reader :key
def initialize(key) # <- not "init"
@key = key
end
def ==(other)
self.class == other.class && self.key == other.key
end
end
==
方法检查两个对象是否具有相同的类(即,如果两个对象都是PixKey
实例)以及它们的key
's是否相等。
这给:
a = PixKey.new('01201201202')
b = PixKey.new('01201201202')
a == b
#=> true
创建一个类方法来创建实例,并让它查找散列。
class PixKey
@@instances = {}
def PixKey.create(id)
if not @@instances.has_key?(id)
@@instances[id] = PixKey.new(id)
end
return @@instances[id]
end
def initialize(id)
@key = id
end
end
a = PixKey.new(123)
b = PixKey.new(123)
c = PixKey.create(123)
d = PixKey.create(123)
puts a
puts b
puts c
puts d
输出:
#<PixKey:0x000000010bc39900>
#<PixKey:0x000000010bc38078>
#<PixKey:0x000000010bc33eb0>
#<PixKey:0x000000010bc33eb0>
注意,用PixKey.create(id)
方法创建的最后两个实例返回相同的实例。
注意Ruby的new
方法只是Class
上的一个方法,可以像其他方法一样被重写。文档描述了默认实现。
调用
allocate
创建类类的新对象,然后调用该对象的initialize
方法,传递参数。这个方法在使用.new
构造对象时最终会被调用。
所以,如果你想保持.new
语法并且仍然得到相同的对象,我们可以在类上重写new
并调用super
。这正是OscarRyz的答案所做的,只是使用.new
和super
,而不是单独的辅助函数。
class PixKey
@@instances = {}
def PixKey.new(id)
if not @@instances.has_key?(id)
@@instances[id] = super(id)
end
return @@instances[id]
end
def initialize(id)
@key = id
end
end
a = PixKey.new(123)
b = PixKey.new(123)
puts a
puts b