В ваших двух примерах вы на самом деле не определяете методы в Class
или Module
;вы определяете одноэлементные методы для объекта, который оказывается Class
или Module
, но может быть практически любым объектом.Вот пример с String
:
Diff = "Use me to access really cool methods"
def Diff.patch
# ...
end
. Вы можете сделать любое из них, и это будет работать, но лучший способ сгруппировать связанные методы - это Module
как обычные методы экземпляра (т.е. безself.
):
module Diff
extend self # This makes the instance methods available to the Diff module itself
def diff ... # no self.
def patch ...
end
Теперь вы можете:
- использовать эту функциональность из любого класса (с
include Diff
) или из любого объекта (с extend Diff
) - примером такого использования является строка
extend self
, которая позволяет вызывать Diff.patch
. - , даже используя эти методы в глобальном пространстве имен
Например, в irb
:
class Foo
include Diff
end
Foo.new.patch # => calls the patch method
Diff.patch # => also calls Diff.patch
include Diff # => now you can call methods directly:
patch # => also calls the patch method
Примечание : extend self
«изменит» сам объект модуля Diff
, но не повлияет на включениямодуля.То же самое происходит с def self.foo
, foo
не будет доступен ни одному классу, включая его.Короче говоря, только методы экземпляра Diff
импортируются с include
(или extend
), а не синглтон-методами.Только наследование класса обеспечит наследование как экземпляров, так и одноэлементных методов.
Когда вы действительно хотите, чтобы включение модуля предоставляло и методы экземпляра, и одноэлементные методы, это не совсем легко.Вы должны использовать self.included
крючок:
module Foo
def some_instance_method; end
module ClassMethods
def some_singleton_method; end
end
def self.included(base)
base.send :extend, ClassMethods
end
def self.will_not_be_included_in_any_way; end
end
class Bar
include Foo
end
# Bar has now instance methods:
Bar.new.some_instance_method # => nil
# and singleton methods:
Bar.some_singleton_method # => nil