防止Ruby中的重复对象

防止Ruby中的重复对象,ruby,singleton,Ruby,Singleton,这并不完全是单身,但很接近,所以我想这是很普遍的。我有一个类(Foo),其中的实例对应于具有唯一id的外部数据结构。我想确保没有两个Foo实例具有相同的ID-如果使用相同的ID值调用构造函数,则使用该ID的原始Foo实例以及所有其他值都将被简单地更新。换句话说,类似于: class Foo def initialize(id, var1, var2) if Foo.already_has? id t = Foo.get_object(id) t.var1 =

这并不完全是单身,但很接近,所以我想这是很普遍的。我有一个类(Foo),其中的实例对应于具有唯一id的外部数据结构。我想确保没有两个Foo实例具有相同的ID-如果使用相同的ID值调用构造函数,则使用该ID的原始Foo实例以及所有其他值都将被简单地更新。换句话说,类似于:

class Foo
  def initialize(id, var1, var2)
    if Foo.already_has? id
      t = Foo.get_object(id)
      t.var1 = var1
      t.var2 = var2
      return t
    else
      @var1 = var1
      @var2 = var2
    end
end
我可以想出两种方法:

  • 我可以保留一个包含所有Foo实例的数组作为类级变量,然后在初始化方法结束时调用Foo_instances.push(self)。我觉得这有点难看

  • 我相信Ruby已经跟踪了某个数组中每个类的实例——如果是的话,这是可访问的吗?它会比#1更好吗

  • ???(Ruby似乎支持一些巧妙的[meta-]编程技巧,因此,如果已经有一种我所缺少的整洁的编程方法,我也不会感到惊讶


  • 您可以覆盖对象中的
    Foo.new
    ,并在其中执行任何操作:

    class-Foo
    def自我更新(id,var1,var2)
    如果instance=self.lookup,则返回instance
    实例=self.allocate
    instance.send:初始化,var1,var2
    返回self.store(实例)
    结束
    结束
    
    显然,您还可以使用不同的类方法来获取对象;将
    initialize
    方法设置为私有,以帮助阻止意外分配

    这样,每个ID只有一个实例,这通常比您建议的模式痛苦得多

    您仍然需要实现
    存储
    查找
    位,在类中没有比
    哈希
    数组
    更好的方法来实现这一点

    您需要考虑将存储在类中的内容包装到一个实例中,但仍然返回真实对象。这样,该类就可以强制执行唯一性,而不会限制使用过的每个ID始终保留在内存中

    这并不适用于你的每一种情况,但肯定适用于某些情况。例如:

    #省略了以前的代码。。。
    返回存储(实例)
    结束
    def self.store(实例)
    @实例| 124;={}
    @实例[instance.id]=WeakRef.new(实例)
    实例
    结束
    def自我查找(id)
    @实例| 124;={}
    如果weakref=@instances[id]和weakref.weakref_还活着?
    返回weakref.uu getobj_u3;包装的实例
    其他的
    归零
    结束
    结束
    
    谢谢你介绍我分配-我没有意识到它的存在。但是,对于查找,有没有比手动创建/管理实例数组更好的方法呢?没有。可能是一个
    散列,但这并没有什么不同。事实上,等等-你几乎肯定想从标准库,在数组中的对象周围-这样它们就不会永远停留:如果删除了一个对象,并且在再次调用构造函数之前没有进行垃圾收集,该怎么办?是否需要在每次调用.new时调用Objectspace.garbage\u collect?我更新了答案,但简言之:不,不要对垃圾收集做任何事情在内部保留一个weakref,但将真实对象返回给调用者,使其保持活动状态。