Including a Module with append_features
2379 ワード
Including a Module with append_features module MyMod
def MyMod.append_features(someClass)
def someClass.modmeth
puts "Module (class) method"
end
super # This call is necessary!
end
def meth1
puts "Method 1"
end
end
class MyClass
include MyMod
def MyClass.classmeth
puts "Class method"
end
def meth2
puts "Method 2"
end
end
x = MyClass.new
# Output:
MyClass.classmeth # Class method
x.meth1 # Method 1
MyClass.modmeth # Module (class) method
x.meth2 # Method 2
This example is worth examining in detail. First, we should understand that append_features isn't just a hook that is called when an include happens; it actually does the work of the include operation. That's why the call to super is needed; without it, the rest of the module (in this case, meth1) wouldn't be included at all.
Also note that within the append_features call, there is a method definition. This looks unusual, but it works because the inner method definition is a singleton method (class-level or module-level). An attempt to define an instance method in the same way would result in a Nested method error.
Conceivably a module might want to determine the initiator of a mixin. The append_features method can also be used for this because the class is passed in as a parameter.
It is also possible to mix in the instance methods of a module as class methods.
module MyMod
def meth3
puts "Module instance method meth3"
puts "can become a class method."
end
end
class MyClass
class << self # Here, self is MyClass
include MyMod
end
end
MyClass.meth3
# Output:
# Module instance method meth3
# can become a class method.
The extend method is useful here. This example simply becomes: class MyClass
extend MyMod
end
module MyMod
def MyMod.append_features(someClass)
def someClass.modmeth
puts "Module (class) method"
end
super # This call is necessary!
end
def meth1
puts "Method 1"
end
end
class MyClass
include MyMod
def MyClass.classmeth
puts "Class method"
end
def meth2
puts "Method 2"
end
end
x = MyClass.new
# Output:
MyClass.classmeth # Class method
x.meth1 # Method 1
MyClass.modmeth # Module (class) method
x.meth2 # Method 2
module MyMod
def meth3
puts "Module instance method meth3"
puts "can become a class method."
end
end
class MyClass
class << self # Here, self is MyClass
include MyMod
end
end
MyClass.meth3
# Output:
# Module instance method meth3
# can become a class method.
class MyClass
extend MyMod
end