2013-01-14 31 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 
相關問題