module ActionsThe
def left(steps)
Movement.new(self, steps)
end
end
Actions
module can be included to allow a class to generate movements.class CarAfter
include Actions
end
Actions
is included left
can be executed by any instance of Car
.car = Car.new
movement = car.left
Similarly, Object.extend(module, ..) adds the instance methods from each module given as a parameter. However,
extend
adds the methods to one instance, not to all instances.car = Car.newThe above code gives car the same behavior as include would, except only the instance that called extend would have this new behavior. Therefore, the above code is valid, but this code would result in an error:
car.extend Actions
movement = car.left
car = Car.new
car.extend Actions
car2 = Car.new
movement = car2.left #calling 'left' here is invalid because car2 does not extend Actions
extend
is commonly used to mix instance methods of a module into a class.module AttributeInitializerMany DSL style class methods are added by extending a module instead of including it.
def attr_init(name, klass)
eval "define_method(name) { @#{name} ||= klass.new }"
end
end
class Statement
extend AttributeInitializer
attr_init :charges, Array
end
For another example of correct
extend
usage see Forwardable from the standard library.
I have been using an Module.included? to add class methods as well:
ReplyDeletemodule Extras
def included?(base)
base.class_eval do
# this will be a new class method
def do_something
puts "it works!"
end
end
end
end
class MyClass
include Extras
end
MyClass.do_something
it has been very handy the past couple of days, though I am not doing a DSL.
If you prefer to use include you can override the append_features(mod) callback. I do exactly that in my previous post.
ReplyDeleteRuby Delegation Module
Thanks. I've been reading the code for authlogic, and now I finally understand why he writes things like:
ReplyDelete...
module Methods
def self.included(klass)
klass.class_eval do
extend ClassMethods
include InstanceMethods
...
Thank you for explanation. I created a DSL method for my implementation using "extend" method.
ReplyDelete'The above code gives car the same behavior as include would, except only the instance that called extend would have this new behavior.'
ReplyDeleteIt seems that when including a module its contents are treated as a superclass of the class that is including it, whereas when extending a module this is not the case.