2013-01-14 30 views
27

Ruby有没有什么方法可以知道它有多少实例存在,并且可以列出它们?如何列出从Ruby中的类创建的所有对象?

下面是一个简单类:

class Project 

    attr_accessor :name, :tasks 

    def initialize(options) 
    @name = options[:name] 
    @tasks = options[:tasks] 
    end 

    def self.all 
    # return listing of project objects 
    end 

    def self.count 
      # return a count of existing projects 
    end 


end 

现在我创建这个类的项目对象:

options1 = { 
    name: 'Building house', 
    priority: 2, 
    tasks: [] 
} 

options2 = { 
    name: 'Getting a loan from the Bank', 
    priority: 3, 
    tasks: [] 
} 

@project1 = Project.new(options1) 
@project2 = Project.new(options2) 

我想什么是有类方法像Project.allProject.count返回的列表和当前项目的数量。

我该怎么做?

回答

40

您可以使用ObjectSpace模块来做到这一点,特别是each_object方法。

ObjectSpace.each_object(Project).count 

为了完整起见,这里是你将如何使用,在你的类(帽尖到萨瓦)

class Project 
    # ... 

    def self.all 
    ObjectSpace.each_object(self).to_a 
    end 

    def self.count 
    all.count 
    end 
end 
+0

你是否需要在类中包含ObjectSpace以使其工作? – onebree

+2

@HunterStevens不,我们不是将模块混入我们的课,只是调用它的一个方法 –

+0

**警告**:这个解决方案可以很容易地在脚下自我射击。如果你不保留对你的对象的引用(例如,如果你没有将结果赋值给'Project.new'),它们将在某个时间点被垃圾回收,'ObjectSpace.each_object'显然会停止报告它们。使用'@@ instances = []'来代替rohit89的答案,通过保留对这些对象的引用来解决这个问题。 – vmarquet

5

一种方法是在创建新实例时跟踪它。

class Project 

    @@count = 0 
    @@instances = [] 

    def initialize(options) 
      @@count += 1 
      @@instances << self 
    end 

    def self.all 
     @@instances.inspect 
    end 

    def self.count 
     @@count 
    end 

end 

如果你想使用ObjectSpace,那么它的

def self.count 
    ObjectSpace.each_object(self).count 
end 

def self.all 
    ObjectSpace.each_object(self).to_a 
end 
+0

这是我会怎么做。它在所有Ruby实现中都能正常工作,并且可以根据需要扩展用于不同的目的。 –

2

也许这将工作:

class Project 
    class << self; attr_accessor :instances; end 

    attr_accessor :name, :tasks 

    def initialize(options) 
    @name = options[:name] 
    @tasks = options[:tasks] 

    self.class.instances ||= Array.new 
    self.class.instances << self 
    end 

    def self.all 
    # return listing of project objects 
    instances ? instances.dup : [] 
    end 

    def self.count 
    # return a count of existing projects 
    instances ? instances.count : 0 
    end 

    def destroy 
    self.class.instances.delete(self) 
    end 
end 

但是你必须手动销毁这些对象。也许其他解决方案可以基于ObjectSpace模块构建。

+0

我喜欢这个,但是应该有一些内置的反射 - 这不是存在于红宝石?我不知道如何使用ObjectSpace模块。例子真的会帮助 –

+1

那么。 ObjectSpace让你与垃圾收集器交互。这是我尝试不在我的代码中做的事情。你可以尝试'ObjectSpace.each_object(Project).to_a',但是我不能再帮你了。 – yattering

+0

为什么要避免这种情况? –

4
class Project 
    def self.all; ObjectSpace.each_object(self).to_a end 
    def self.count; all.length end 
end 
相关问题