Я читал несколько статей о методах Ruby mixin, extend
и include
, и я все еще не совсем уверен в поведении. Я понимаю, что extend
добавит методы экземпляра данного модуля как однотонные методы к модулю, выполняющему расширение, и что include
по существу добавит содержимое модуля (методы, константы, переменные) к тому, которое делает в том числе, эффективно определяя их в приемнике.
Однако, после некоторого возиться, пытаясь понять, как будет проявляться поведение, у меня есть несколько вопросов. Вот моя настройка тестирования:
module Baz
def blorg
puts 'blorg'
end
end
module Bar
include Baz
def blah
puts 'blah'
end
end
module Foo
extend Bar
end
class Bacon
extend Bar
end
class Egg
include Bar
end
Как и следовало ожидать, модуль Bar
получает методы экземпляра, определенные в Baz
(#blorg
), как если бы они были определены сами по себе из-за метода включения, а класс Bacon
методы Bacon::blah
и Bacon::blorg
по расширению.
Bacon.blah # => blah
Bacon.blorg # => blorg
И класс Egg
получает методы, определенные в Bar
(#blah
и теперь #blorg
) как методы экземпляра.
Egg.new.blah # => blah
Egg.new.blorg # => blorg
Я получаю все это, так что хорошо.
Однако я не понимаю ответов, получаемых от методов #ancestors
и #is_a?
.
Bacon.ancestors # => [Bacon, Object, Kernel, BasicObject]
Bacon.is_a? Bar # => true
Egg.ancestors # => [Egg, Bar, Baz, Object, Kernel, BasicObject]
Egg.is_a? Bar # => false
Казалось бы, расширение модуля заставляет метод #is_a?
возвращать true
при запросе об этом модуле, но он не добавляется к предкам класса, и наоборот в отношении включения: предки класс содержит включенные модули, но метод #is_a?
возвращает false
при запросе. Почему это происходит?