2016-01-25 31 views
1

我想查找在運行時在ruby腳本中創建的類的列表/總和。如何獲得在ruby腳本中創建的所有對象類型的列表

我這樣做

# rewrite class in order to display ClassName when GCed" 
# 
$objs = [] 
class Class 
    alias oldNew new 
    def new(*args) 
    inst = oldNew(*args) 
    $objs << inst.class.name unless $objs.include?(inst.class.name) 
    inst 
    end 
end 
# some code 
puts $bjs 

有沒有更好的方式來做到這一點?

我曾嘗試使用:

$objs = [] 
class Class 
    alias oldNew new 
    def new(*args) 
    inst = oldNew(*args) 
    ObjectSpace.define_finalizer(inst, proc {|id| puts "Finalizer one on #{id.name}" }) 
    inst 
    end 
end 

但我沒有輸出。

僅供參考我測試的一些代碼使用C擴展名。

編輯 更具體的代碼:

require "gtk3" 
require "objspace" 


$objs = [] 
class Class 
    alias oldNew new 
    def new(*args) 
    inst = oldNew(*args) 
    # This doesn't work 
    # ObjectSpace.define_finalizer(inst, proc {|id| puts "Finalizer one on #{id.name}" }) 
    $objs << inst.class.name unless $objs.include?(inst.class.name) 
    inst 
    end 
end 

TITLE_COLUMN = 0 
AUTHOR_COLUMN = 1 
CHECKED_COLUMN = 2 

model = Gtk::TreeStore.new(String, String, TrueClass) 
iter = model.append(nil) 
iter[TITLE_COLUMN] = "The Principle of Reason" 
iter[AUTHOR_COLUMN] = "Martin Heidegger" 
iter[CHECKED_COLUMN] = false 

iter = model.append(nil) 
iter.set_values(["The Art of Computer Programming", "Donald E. Knuth", true]) 

# append child 
child_iter = model.append(iter) 
child_iter[TITLE_COLUMN] = "Volume 1: Fundamental Algorithms" 

# append another child 
child_iter = model.append(iter) 
child_iter.set_value(TITLE_COLUMN, "Volume 2: Seminumerical Algorithms") 
child_iter.set_value(CHECKED_COLUMN, true) 

# append another child 
child_iter = model.append(iter) 
child_iter.set_values(["Volume 3: Sorting and Searching", "Donald E. Knuth", true]) 

def treeview_widget_of(model) 
    treeview = Gtk::TreeView.new(model) 
    treeview.append_column(Gtk::TreeViewColumn.new("Title", Gtk::CellRendererText.new, { :text => TITLE_COLUMN })) 
    treeview.append_column(Gtk::TreeViewColumn.new("Author", Gtk::CellRendererText.new, { :text => AUTHOR_COLUMN })) 
    treeview.append_column(Gtk::TreeViewColumn.new("Author", Gtk::CellRendererToggle.new, { :active => CHECKED_COLUMN })) 
    treeview 
end 

def display_model(model) 
    win = Gtk::Window.new(:toplevel) 
    win.title = "Simple Gtk::TreeStore" 
    win.add(treeview_widget_of(model)) 
    win.show_all 
    win.signal_connect("destroy") { Gtk.main_quit } 
    Gtk.main 
end 

display_model(model) 
puts $objs.inspect 

編輯2

["Gio::Loader", "Class", "Module", "GObjectIntrospection::TypeTag", "GObjectIntrospection::Direction", "GObjectIntrospection::FieldInfoFlags", "GObjectIntrospection::ScopeType", nil, "LoadError", "Gdk::Loader", "Gtk::Loader", "Gtk::TreeStore", "GLib::Value", "Gtk::Window", "Gtk::TreeView", "Gtk::CellRendererText", "Gtk::TreeViewColumn", "Gtk::CellRendererToggle"] 
+0

你能舉幾個例子,即填寫'一些代碼#some code'? – Stefan

+0

當然。查看編輯部分 – cedlemo

+1

你的問題是什麼?你共享的代碼有一些輸出 - 那個輸出有什麼錯誤,你的期望輸出是什麼。 –

回答

1

下面是Jörg W Mittag's comment代碼段的變化:

require 'objspace' 
def monitor_classes 
    b = [] 
    a = [] 
    ObjectSpace.each_object { |o| a << o.__id__ } 
    yield 
    ObjectSpace.each_object { |o| b << o.__id__ } 
    (b - a).map { |id| ObjectSpace._id2ref(id).class }.uniq 
end 

monitor_classes do 
    'str' 
end 
#=> [String] 

monitor_classes do 
    [] 
end 
#=> [Array] 

monitor_classes do 
    {} 
end 
#=> [Hash] 

monitor_classes do 
    loop 
end 
#=> [Enumerator] 
+0

我喜歡你的答案,但與它我仍然有同樣的問題試試:puts - (monitor_classes {a =「toto」 ; b = a.size})。檢查。它返回[String],但b是一個數字,它不會出現。 – cedlemo

+1

@cedlemo與其他對象不同,Ruby不會*創建*'Fixnum'對象。它們具有即時的價值,因此'ObjectSpace'不能跟蹤它們。 – Stefan

+0

當我的例子iter = model.append(nil)中的這一行被執行時,它是否是同樣的東西?變量模型是一個Gtk :: TreeStore實例,它是一個Gtk :: TreeIter實例,但我無法跟蹤它存在/創建。 – cedlemo

4

這是非常簡單的:

require 'objspace' 

ObjectSpace.each_object(Class) 

但是請注意,這將ONL Ÿ給你,和不是的類型。一個對象的類型就是它所說的協議,但在Ruby語言中沒有這種表示方式,全都在程序員的腦海中。

例如,我將調用Appendable,該類型的特徵是響應<<的對象self以及作爲將參數添加到其內部狀態的副作用。數組和字符串都是Appendable,儘管它們不共享除Object之外的任何共同祖先類。還請注意,即使Integer<<作出響應,但它不是Appendable

還有另一種類型我將調用Iterable,其特點是一個物體響應eachself和作爲副作用yield制定其下屬元素到塊。 mixin依賴於這種類型,但在Ruby中無法表達這種依賴關係,因此必須在文檔中對其進行外部聲明,或者在這種特殊情況下,這只是Ruby社區中根深蒂固的常識。

+2

您的代碼將枚舉所有類,而不僅僅是腳本創建的類(特別是無論是什麼意思)。 – Stefan

+2

嗯,這個問題說「在」一個腳本,而不是「通過」一個腳本。我將其解釋爲意味着由於運行腳本而創建的類,即腳本末尾存在的類。但你的解釋也是有效的。這兩種解釋之間的區別基本上只是腳本開始時的'existing = ObjectSpace.each_object(Class)',然後是'existing.to_a - ObjectSpace.each_object(Class).to_a'。 –

+1

它也說*「在運行時間」*,但這也可以解釋任何方式;-) – Stefan

相關問題