Почему метод расширения не ставит ценность - PullRequest
2 голосов
/ 14 июня 2011
module Lab
  def self.foo
    puts 'foo from lab'
  end
end

module M
  def foo
    puts 'foo from module'
    super
  end
end

module Lab
  extend M
end

Lab.foo

Я ожидал, что увижу

foo from module
foo from lab

Однако я получаю

foo from lab

Я пытаюсь перехватить значениеметод из драгоценного камня и сделать что-то.Я могу использовать alias_method_chain, но я стараюсь не использовать это.

Ответы [ 3 ]

1 голос
/ 14 июня 2011

Если вы ожидаете

foo from module
foo from lab

Тогда вам нужно поместить super в Lab # foo, вот так:

module Lab
  def self.foo
    super
    puts 'foo from lab'
  end
end

module M
  def foo
    puts 'foo from module'
  end
end

module Lab
  extend M
end

Lab.foo
1 голос
/ 14 июня 2011

Методы, определенные в Lab, имеют непосредственное преимущество перед методами, определенными в модулях, таких как M, которые расширяются Lab.

Таким образом, foo, определенный непосредственно в Lab, имеет приоритет над M#foo, хотя Lab.extend M.

Чтобы получить то, что вы хотите, сделайте следующее:

module Lab
  module HasFoo
    # foo isn't defined directly on Lab directly anymore;
    # instead, it is defined in a separate module that
    # Lab extends
    def foo
      puts "foo from lab"
    end
  end

  extend HasFoo
end

module M
  def foo
    puts "foo from module"
    super
  end
end

module Lab
  # when Lab extends another module with foo, that changes
  # which concrete method the name foo gets resolved to
  extend M
end

# now you should see the module foo and then the lab foo
Lab.foo
0 голосов
/ 14 июня 2011

Когда вы включаете / расширяете модуль M до класса C и вызываете метод C#method или C.method, который также определен для M, тогда C имеет приоритет над M в пути поиска метода. Другими словами, вы не можете перезаписать метод путем включения / продления. Вы можете добавлять только новые методы. См. этот связанный вопрос.

В вашем случае, Lab.foo называется просто. Следующее (без Lab.foo) даст вам желаемый результат.

module M
  def foo
    puts 'foo from module'
  end
end

module Lab
  extend M
end

Lab.foo

# => foo from module

Обратите внимание, что суперкласс вашего M равен Module, и, поскольку Module#foo не определен, следующее вызовет ошибку.

module M
  def foo
    puts 'foo from module'
    super
  end
end

module Lab
  extend M
end

Lab.foo

# => method undefined error
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...