Почему порядок включения модулей имеет значение в Ruby? - PullRequest
0 голосов
/ 03 декабря 2008

Этот вопрос лучше всего суммировать с примером кода:

module TestOne
  module Foo
    def foo
      42
    end
  end

  module Bar
    include Foo
  end

  class Quux
    include Bar
  end
end

TestOne::Bar.ancestors # => [TestOne::Bar, TestOne::Foo]
TestOne::Quux.ancestors # => [TestOne::Quux, TestOne::Bar, TestOne::Foo, Object, Kernel]
TestOne::Quux.new.foo # => 42

module TestTwo
  class Quux
  end

  module Bar
  end

  module Foo
    def foo
      42
    end
  end
end

TestTwo::Quux.send :include, TestTwo::Bar
TestTwo::Bar.send :include, TestTwo::Foo

TestTwo::Bar.ancestors # => [TestTwo::Bar, TestTwo::Foo]
TestTwo::Quux.ancestors # => [TestTwo::Quux, TestTwo::Bar, Object, Kernel]
TestTwo::Quux.new.foo # => 
# ~> -:40: undefined method `foo' for #<TestTwo::Quux:0x24054> (NoMethodError)

Я думал, что когда вы включаете модуль (например, Bar в класс Foo), все, что Ruby хранит, это тот факт, что Foo включает Bar. Итак, когда вы вызываете метод в Foo, он ищет в Bar метод.

Если это было правдой, к тому времени, когда вызывается TestTwo::Quux.new.foo, я смешал метод foo с TestTwo::Bar, поэтому он должен работать, верно?

1 Ответ

3 голосов
/ 03 декабря 2008

В документах сказано, что append_features (который вызывается методом include) смешивает методы с вызывающей стороной. Поэтому, когда TestTwo::Quux включает TestTwo::Bar, к TestTwo::Quux не добавляются никакие методы. Следующая строка добавляет методы к TestTwo::Bar, но не к TestTwo::Quux.

...