Как получить доступ к модулю из метода экземпляра в Ruby?
Предположим, у меня есть модуль:
module M
def self.foo
...
end
def bar
...
end
end
модуль M
входит в класс.
class A
include M
end
Я хочу позвонить foo
от bar
, который в конечном итоге будет вызван на экземпляр A
, Какой лучший способ сделать это внутри bar
?
Конечно я могу просто сказать M.foo
, но это дублирование имени модуля, которое кажется ненужным.
3 ответа
Обычно в module
Хорошей практикой является разделение методов класса и методов экземпляра следующим образом:
module M
def bar
puts "BAR"
self.class.foo
end
module ClassMethods
def foo
puts "FOO"
end
end
end
Теперь, в классе, я бы идеально хотел include
этот модуль M
таким образом, что я получаю A.foo
как метод класса и A.new.bar
как метод экземпляра. Трюк для этого Module.included
,
module M
def bar
puts "BAR"
self.class.foo
end
module ClassMethods
def foo
puts "FOO"
end
end
# when module is included, extend the class with ClassMethods
def self.included(base)
base.extend ClassMethods
end
end
class A
include M
end
A.singleton_methods #=> [:foo]
A.new.foo
#=> BAR
#=> FOO
При таком подходе вы можете ссылаться на метод класса с self.class
и это будет работать автоматически.
Надеюсь, поможет.
Я думаю, используя M.foo
лучше, но в качестве упражнения можно изменить M#bar
следующее.
module M
def self.foo
puts "In self.foo"
end
def bar
puts "In bar"
method(__method__).owner.foo
end
end
class A
include M
end
a = A.new
a.bar
# In bar
# In self.foo
Не очень элегантно, но
def bar
Module.nesting.last.foo
end
должен сделать это.
Обратите внимание, что Module#nesting
возвращает массив, потому что один модуль может быть вложен в другой модуль. В общем случае вам нужно применить правильный индекс массива, чтобы выбрать модуль, который вы хотите иметь.