2012-07-16 30 views
7
module A; def a; end; end 
module B; def b; end; end 

class C; include A; end 

module A; include B; end 
class D; include A; end 

C.new.b # undefined method error 
D.new.b # nil 

C.ancestors # [C, A, Object...] 
D.ancestors # [D, A, B, Object...] 

Modül A'nın içerisine nasıl eklenir, böylece A modülünü içeren sınıflar ayrıca B modülünden yöntemler alır mı?Diğer modülde bir modül de dahil olmak üzere

+0

Nihayetinde, burada ne elde etmek istiyorsunuz? Kullanım durumunuzu somut bir örnekle açıklayabilir misiniz? Belki senin problemin farklı şekilde ele alınabilir. – Wei

+0

Modülümü 'ActionDispatch :: Routing :: UrlFor' Rails modülüne dahil etmek istedim, böylece bunu içeren tüm Rails sınıfları otomatik olarak yeni yöntemlerimi de alacaktı. Farklı bir şekilde çözdüm, ama bu şekilde çalışmadığından çok şaşırdım. – szimek

cevap

2

Yapamazsın.

bir sınıfa C içine mixin M, Yakut yöntemi tablo noktaları mixin M yöntemi tabloya ve kimin üst sınıf C üst sınıfı olan yeni bir sınıf ⟦M′⟧ oluşturur include sonra bu sınıfı yeni üst sınıf yapar C. Bu, M'a karıştırılmış her karışım için tekrarlanır.

Bu algoritmanın, M'u C'a karıştırdığınızda yalnızca bir kez çalıştığını unutmayın. Daha sonra include d alan modüller dikkate alınmayacaktır.

1

C sınıfından önce B'yi B'ye dahil etmelisiniz; içeriyor;.

module A; def a; end; end 
module B; def b; end; end 


module A; include B; end 

class C; include A; end 
class D; include A; end 

p C.new.b # nil 
p D.new.b # nil 

p C.ancestors # [C, A, B, Object, Kernel, BasicObject] 
p D.ancestors # [D, A, B, Object, Kernel, BasicObject] 

Düzenleme

module A; def a; end; end 
module B; def b; end; end 

class C; include A; end 

module A; include B; end 
class D; include A; end 

C.send(:include, A) 

p C.new.b # nil 
p D.new.b # nil 

p C.ancestors # [C, A, Object...] 
p D.ancestors # [D, A, B, Object...] 
+1

Sınıfların bu modülleri içerdiği sırayı değiştiremiyorum. Rails 'ActionDispatch :: Routing :: UrlFor' modülünü, Rails sınıflarında zaten mevcut olan uzatmaya çalışıyorum – szimek

+0

Bu ne' ActiveSupport :: Concern' için üretilmiş değil mi? –

+0

Teşekkürler, ancak buradaki fikir, modülümü 'ActionDispatch :: Routing :: UrlFor' içine dahil etmekti. Bu sayede, içerdiği tüm Rails sınıfları bu yeni yöntemleri alacaktır. Bu modülü içeren her Rails sınıfında yinelemek istemiyorum. Tüm bu sınıfların bir listesi olsaydı, modülümü doğrudan onlara dahil edebilirdim. – szimek

3

Daha önce de belirtildiği gibi, Ruby bu şekilde çalışmaz - bir sınıf bir modül içeriyorsa, modülün diğer modülleri içeriyorsa, bu nedenle bu modülün örneğine herhangi bir başvuruda bulunmaz. zaten dahil, değişim hakkında bilmeyecek.

Modüle kendisinde modülü dahil sınıfları depolayarak bu çevrede alabilir - modülü başka bir modül, yani böyle bir şey eklediğinde bu şekilde bunları güncelleyebilirsiniz:

module A 

    class<<self 
    attr_accessor :observers 
    end 

    self.observers = [] 

    def a 
    "#{self} successfully called a" 
    end 

    def self.included(base) 
    self.observers << base unless self.observers.include?(base) 
    end 

    def self.include(mod) 
    observers.each {|o| o.send(:include,mod) } 
    super 
    end 

end 

module B 
    def b 
    "#{self} successfully called b" 
    end 
end 

class C 
    include A 
end 

module A 
    include B 
end 

class D 
    include A 
end 

module E 
    def e 
    "#{self} successfully called e" 
    end 
end 

module A 
    include E 
end 

puts C.new.b 
puts D.new.b 
puts C.new.e 
puts D.new.e 

emin değil bu Almak istediğiniz yön, ancak prensipte yapılabileceğini gösterir.

İlgili konular