Mixins'i anlamanın en iyi yolu sanal sınıflardır. Karışımlar, bir sınıfın veya modülün üst zincirine enjekte edilmiş "sanal sınıflardır".
"İnclude" komutunu kullandığımızda ve ona bir modül ilettiğimizde, modülü miras aldığımız sınıfın hemen önüne ata zincirine ekler:
class Parent
end
module M
end
class Child < Parent
include M
end
Child.ancestors
=> [Child, M, Parent, Object ...
Ruby'deki her nesnenin ayrıca bir singleton sınıfı vardır. Bu tekil sınıfa eklenen yöntemler doğrudan nesnede çağrılabilir ve bu nedenle "sınıf" yöntemler olarak hareket ederler. Bir nesne üzerinde "expand" kullandığımızda ve nesneye bir modül ilettiğimizde, modülün yöntemlerini nesnenin singleton sınıfına ekliyoruz:
module M
def m
puts 'm'
end
end
class Test
end
Test.extend M
Test.m
Singleton sınıfına singleton_class yöntemi ile erişebiliriz:
Test.singleton_class.ancestors
=> [#<Class:Test>, M, #<Class:Object>, ...
Ruby, sınıflara / modüllere karıştırılırken modüller için bazı kancalar sağlar. included
Ruby tarafından sağlanan ve bir modül veya sınıfa bir modül eklediğinizde çağrılan bir kanca yöntemidir. Dahil edildiği gibi, extended
uzatma için ilişkili bir kanca vardır . Bir modül başka bir modül veya sınıf tarafından genişletildiğinde çağrılacaktır.
module M
def self.included(target)
puts "included into #{target}"
end
def self.extended(target)
puts "extended into #{target}"
end
end
class MyClass
include M
end
class MyClass2
extend M
end
Bu, geliştiricilerin kullanabileceği ilginç bir model oluşturur:
module M
def self.included(target)
target.send(:include, InstanceMethods)
target.extend ClassMethods
target.class_eval do
a_class_method
end
end
module InstanceMethods
def an_instance_method
end
end
module ClassMethods
def a_class_method
puts "a_class_method called"
end
end
end
class MyClass
include M
# a_class_method called
end
Gördüğünüz gibi, bu tek modül örnek yöntemler, "sınıf" yöntemler ekliyor ve doğrudan hedef sınıf üzerinde hareket ediyor (bu durumda a_class_method () 'u çağırıyor).
ActiveSupport :: Concern bu kalıbı özetler. ActiveSupport :: Concern'i kullanmak için yeniden yazılmış aynı modül:
module M
extend ActiveSupport::Concern
included do
a_class_method
end
def an_instance_method
end
module ClassMethods
def a_class_method
puts "a_class_method called"
end
end
end