Pytanie Ruby: moduły i super?


Nie rozumiem, dlaczego to działa.

module Base
  attr_reader :first
  def setup
    @first = 1
  end
end

module Addon
  attr_reader :second
  def setup
    #super
    @second = 2
  end
end

class Test
  include Base
  include Addon

  def initialize(num)
    @num = num
    setup
  end
end

a = Test.new(1)
p a.first
p a.second

Zasadniczo mam "podstawowy" moduł, który ustawia pewne rzeczy. Mam również moduł addon, który ustawia trochę więcej rzeczy, jeśli jakaś klasa chce to uwzględnić.

Teraz, kiedy testuję to, jeśli nie mam tego super połączenia, dostaję

nil
2

Kiedy mam super połączenie, dostaję

1
2

Co super tutaj robi? Wywołuje metodę konfiguracji z modułu Base, nawet gdy Base i Addon nie są ze sobą powiązane.

Po raz pierwszy użyłem super w kontekście modułów. Wcześniej zawsze używałam super połączeń z klasami i myślałam, że chodzi po prostu o drzewo dziedziczenia, aby znaleźć rodzica za pomocą tej samej metody.

Czy zawiera wiele modułów, które również tworzą drzewo dziedziczenia?

EDYCJA: dla kontekstu moduł Addon nigdy nie będzie dołączony bez modułu Base, a moduł Base zawsze będzie dołączany przed dodatkowymi modułami Addon.


21
2017-07-09 21:58


pochodzenie


Myślę, że masz rację. Sygnatury metody są prawdopodobnie przechowywane w stosie i super po prostu wysyła wiadomość do obiektu, który znajduje się głębiej w stosie. Interesujące znalezisko, które powiem! - Candide


Odpowiedzi:


Tak, po dołączeniu modułów są one wstrzykiwane do łańcucha dziedziczenia

Test.ancestors # => [Test, Addon, Base, Object, Kernel, BasicObject]

Addon moduł, gdy jest zawarty, zmienia na nowo istniejące setup metoda z Base. Jeśli chcesz Basejego wersja nazywa się, użyj super.


28
2017-07-09 22:33