2013-07-20 1 views
0

Я хочу отслеживать все экземпляры класса, и следующий код работает отлично, но не очень DRY.Ruby дедупликации и экземпляры отслеживания

class BaseClass 
end 

class ClassA < BaseClass 
    @@instances = [] 
    attr_accessor :name 

    def initialize(name) 
    @name = name 
    @@instances << self 
    end 
    def self.list 
    @@instances 
    end 
    def to_s 
    @name 
    end 
end 

class ClassB < BaseClass 
    @@instances = [] 
    attr_accessor :name 

    def initialize(name) 
    @name = name 
    @@instances << self 
    end 
    def self.list 
    @@instances 
    end 
    def to_s 
    @name 
    end 
end 

puts "Creating instances" 
a = ClassA.new "a" 
aa = ClassA.new "aa" 
b = ClassB.new "b" 

puts "Listing for ClassA" 
puts ClassA.list 
puts "Listing for ClassB" 
puts ClassB.list 

Выходной сигнал, который становится

Creating instances 
Listing for ClassA 
a 
aa 
Listing for ClassB 
b 

Perfect. Однако, когда я пытаюсь DeDupe это как так

class BaseClass 
    @@instances = [] 
    attr_accessor :name 

    def initialize(name) 
    @name = name 
    @@instances << self 
    end 
    def self.list 
    @@instances 
    end 
    def to_s 
    @name 
    end 
end 

class ClassA < BaseClass 
end 

class ClassB < BaseClass 
end 

puts "Creating instances" 
a = ClassA.new "a" 
aa = ClassA.new "aa" 
b = ClassB.new "b" 

puts "Listing for ClassA" 
puts ClassA.list 
puts "Listing for ClassB" 
puts ClassB.list 

я получаю следующие выходные данные

Creating instances 
Listing for ClassA 
a 
aa 
b 
Listing for ClassB 
a 
aa 
b 

Это имеет смысл, потому что @@instances был определен в BaseClass и совместно с ClassA и ClassB.

Как я могу получить мой код, дедуплицированный, чтобы выглядеть как последний пример, так что он ведет себя как прежний пример?

ответ

0

Самый простой способ - избавиться от трюка, который вы пытаетесь сделать, и использовать ObjectSpace.each_object.

class BaseClass 
    attr_accessor :name 
    def initialize(name); @name = name end 
    def to_s; @name end 
end 

class ClassA < BaseClass; end 

class ClassB < BaseClass; end 

puts "Creating instances" 
a = ClassA.new "a" 
aa = ClassA.new "aa" 
b = ClassB.new "b" 
puts "Listing for ClassA" 
puts ObjectSpace.each_object(ClassA).to_a 
puts "Listing for ClassB" 
puts ObjectSpace.each_object(ClassB).to_a 

Это дает

Creating instances 
Listing for ClassA 
aa 
a 
Listing for ClassB 
b 
+0

Совершенная. Для полноты я обновил функцию списка, чтобы def self.list; ObjectSpace.each_object (Object.const_get (name)). To_a end – zeroXten