В чем разница между "включить модуль" и "расширить модуль" в Ruby?
Возможный дубликат:
В чем разница между включением и расширением в Ruby?
Учитывая:
module my_module
def foo
...
end
end
Вопрос 1
В чем разница между:
class A
include my_module
end
и
class A
extend my_module
end
Вопрос 2
Будет ли foo
рассматриваться как метод экземпляра или метод класса?
Другими словами, это эквивалентно:
class A
def foo
...
end
end
или:
class A
def self.foo
...
end
end
?
Ответы
Ответ 1
Я написал сообщение в блоге об этом давным-давно здесь.
Когда вы включаете "модуль", модуль включается так, как если бы методы были определены в классе, включающем их, вы могли бы сказать, что он копирует методы в класс включения.
Когда вы "расширяете" модуль, вы говорите "добавьте методы этого модуля в этот конкретный экземпляр". Когда вы находитесь внутри определения класса и говорите "расширяете", "экземпляр" - это сам объект класса, но вы также можете сделать что-то подобное (как в моем сообщении в блоге выше):
module MyModule
def foo
puts "foo called"
end
end
class A
end
object = A.new
object.extend MyModule
object.foo #prints "foo called"
Итак, это не совсем метод класса, а метод к "экземпляру", который вы назвали "расширяем". Поскольку вы делаете это внутри определения класса, и экземпляр в нем есть сам класс, он "похож" на метод класса.
Ответ 2
1) include
добавляет методы, константы и переменные в экземпляры класса A
; extend
добавляет эти вещи к экземпляру Class
instance A
(эффективно определяя методы класса).
include my_module
позволит следующее: A.new.foo
extend my_module
позволит: A.foo
В общем случае include
имеет смысл только в Class
или Module
, а extend
может использоваться для добавления методов к любому Object
.
2) По сути: при использовании include
foo
является методом экземпляра A
... при использовании extend
, foo
является методом класса.