วิธีที่ดีที่สุดที่ฉันเข้าใจมิกซ์อินคือคลาสเสมือน Mixins คือ "คลาสเสมือน" ที่ถูกฉีดเข้าไปในห่วงโซ่บรรพบุรุษของคลาสหรือโมดูล
เมื่อเราใช้ "รวม" และส่งผ่านโมดูลมันจะเพิ่มโมดูลลงในห่วงโซ่บรรพบุรุษก่อนคลาสที่เรากำลังสืบทอดจาก:
class Parent
end
module M
end
class Child < Parent
include M
end
Child.ancestors
=> [Child, M, Parent, Object ...
ทุกออบเจ็กต์ใน Ruby ยังมีคลาสซิงเกิล เมธอดที่เพิ่มเข้าไปในคลาสซิงเกิลนี้สามารถเรียกได้โดยตรงบนอ็อบเจ็กต์ดังนั้นจึงทำหน้าที่เป็นเมธอด "คลาส" เมื่อเราใช้ "ขยาย" บนวัตถุและส่งผ่านวัตถุไปยังโมดูลเรากำลังเพิ่มวิธีการของโมดูลไปยังคลาสซิงเกิลตันของวัตถุ:
module M
def m
puts 'm'
end
end
class Test
end
Test.extend M
Test.m
เราสามารถเข้าถึงคลาส singleton ด้วยเมธอด singleton_class:
Test.singleton_class.ancestors
=> [#<Class:Test>, M, #<Class:Object>, ...
Ruby จัดเตรียมตะขอสำหรับโมดูลเมื่อถูกผสมเข้ากับคลาส / โมดูล included
เป็นวิธีการเชื่อมต่อโดย Ruby ซึ่งจะถูกเรียกเมื่อใดก็ตามที่คุณรวมโมดูลไว้ในโมดูลหรือคลาสบางอย่าง เช่นเดียวกับที่รวมมีextended
ตะขอเกี่ยวสำหรับการขยาย จะถูกเรียกใช้เมื่อโมดูลถูกขยายโดยโมดูลหรือคลาสอื่น
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
สิ่งนี้ทำให้เกิดรูปแบบที่น่าสนใจที่นักพัฒนาสามารถนำไปใช้ได้:
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
อย่างที่คุณเห็นโมดูลเดียวนี้กำลังเพิ่มอินสแตนซ์เมธอดเมธอด "คลาส" และทำหน้าที่โดยตรงกับคลาสเป้าหมาย (ในกรณีนี้เรียก a_class_method ())
ActiveSupport :: ความกังวลห่อหุ้มรูปแบบนี้ นี่คือโมดูลเดียวกันที่เขียนใหม่เพื่อใช้ ActiveSupport :: Concern:
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