2009-11-14 21 views
12

Ben initialize içinde bir attr_accessor ardından bir instance_eval yapmaya çalışıyorum ve bu almaya devam: `` başlatmak ': tanımsız yöntemi' attr_accessor'`. Neden bu çalışmıyor?Neden attr_accessor içeride başlatmak kullanabilir ki?

kod şöyle tür görünür: attr_accessor Sınıfım örnek yöntemi olarak tanımlanmadığı, çünkü örneğinde attr_accessor diyemezsin

class MyClass 
    def initialize(*args) 
     instance_eval "attr_accessor :#{sym}" 
    end 
end 

cevap

20

. Sadece modüller ve sınıflarda kullanılabilir.

class MyClass 
    def initialize(varname) 
    class <<self 
     self 
    end.class_eval do 
     attr_accessor varname 
    end 
    end 
end 

o1 = MyClass.new(:foo) 
o2 = MyClass.new(:bar) 
o1.foo = "foo" # works 
o2.bar = "bar" # works 
o2.foo = "baz" # does not work 
+0

class_eval varname değerini varsayarak: Sadece yazmaya gerek Eğer kendi kendine – johannes

+4

No yazdığı yer, öyle değil. sınıf << kendini; ... ”sonu bir kapanış değil. İçinde 'varname 'erişemezsiniz, ancak' class_eval 'bloğuna erişebilirsiniz. – sepp2k

+0

[semiomant cevabı] (http://stackoverflow.com/a/14978624/403664) iyidir. buna bir bak. –

4

Bir temizlikçi uygulaması (NB: Aşağıdaki Bu bakınız, sınıf, sadece tek örneğinin TÜM örneklerine erişimci katacak görüşlere ben böyle, örneğinin üzerinde metaclass attr_accessor aramak istediğiniz şüpheli):

class MyClass 
    def initialize(varname) 
    self.class.send(:attr_accessor, varname) 
    end 
end 
+6

Bu MyClass' 'bir örnek yöntemi olarak erişimci tanımlar. Eğer var ise 'o1 = MyClass.new (: foo)' ve 'o2 = MyClass.new (: bar) hem' foo' ve 'bar' için erişenleri o2'' hem 'o1' ve' olmadığı amaçlanan davranış. – sepp2k

+0

Oldukça doğru! İşte teknem var. Bu cevabı buraya gelebilecek herhangi bir kişi için (yorumunuzla birlikte) burada bırakacağım. –

+0

Rob'un çözümü çok daha temiz görünüyor. Ama sepp2k'in çözümüne bağlı kalacağım, yalnızca bir örnek için erişim sağlayıcıları kullanacağım. – JAkk

4

Rob d'Apice o neredeyse hakkına sahiptir. koyarak aynıdır

self.singleton_class.send(:attr_accessor, varname) 

veya

self.singleton_class.class_eval "attr_accessor :#{varname}" 

ya benim favori varyantını

self.singleton_class.class_exec do attr_accessor varname end 

bir sembol

İlgili konular