如何创建具有相同对象id的Ruby类



我需要创建一个类,如果属性值是相同的,它不会生成一个新的对象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的答案所做的,只是使用.newsuper,而不是单独的辅助函数。

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

相关内容

  • 没有找到相关文章

最新更新