Я читал несколько статей о методах 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 при запросе. Почему это происходит?