In-Depth Ruby: Modules & Include vs. Extend

Ruby dostarcza konstruktora o nazwie Module, który jest czymś w rodzaju cienkiej klasy. Na początku Programiści Ruby mogą patrzeć na moduły jak na” szufladę śmieci ” kodu, która jest po prostu wyrzucana i używana do porządkowania plików, ale jest pewna metoda tego szaleństwa. Klasa Ruby Class dziedziczy z Module I dodaje takie rzeczy jak instancje, właściwości itp. – wszystko, co normalnie można by pomyśleć, że Klasa miałaby. Ponieważ Module jest dosłownie przodkiem Class, oznacza to, że moduły mogą być w pewien sposób traktowane jak Klasy.

najważniejsze, aby zrozumieć, jak działa Łańcuch przodków Ruby. Jak wszystkie języki OOP, Ruby wspiera dziedziczenie. Kiedy dziedziczysz po klasie, Klasa nadrzędna jest dodawana do łańcucha przodków. Możesz wyświetlić przodków dowolnej klasy, wywołującancestors na niej:

class Foo < BarendFoo.ancestors#=> 

jak wspomniano, możesz znaleźćModule w tablicyClass.ancestors.

gdyinclude moduł do twojej klasy, moduł jest dodawany do łańcucha przodków twojej klasy – tak jak Klasa. To sprawia, że include jest tylko formą dziedziczenia, nie ma w tym nic specjalnego.

module Barendclass Foo include BarendFoo.ancestors#=> 

wszystkie metody wBar są dodawane doFoo jako metody instancji. Ponieważ Bar znajduje się w łańcuchu, możesz nawet wywołać super z niego, aby wywołać metody nad nim w łańcuchu, niezależnie od tego, czy są zdefiniowane w modułach czy klasach.

class Baz def hello p 'world' endendmodule Bar def hello p 'hello' super endendclass Foo < Baz include BarendFoo.new.hello#=> hello world

mimo żeBar jest modułem,super nadal wywołuje łańcuch i takBaz#hello jest również wywoływany. Warto zauważyć, że Bar jest dodawany do łańcucha przodków przed Baz. Gdy moduł jest dołączony, jest zawsze dodawany bezpośrednio na jego klasie. Może to być mylące podczas dodawania wielu modułów, ponieważ są one zawarte w kolejności „odwrotnej” :

class Foo include A include BendFoo.ancestors#=> 

gdyA jest dołączony, jest wstawiany bezpośrednio nadFoo. Ale gdy B jest dołączony, jest również wstawiany bezpośrednio nad Foo, więc ląduje przed A.

include vs extend

include jest wystarczająco łatwe do zrozumienia, dodaje metody modułu jako metody instancji do jego klasy. Możesz pomyśleć o tym, że extend robi to samo, ale zamiast tego dodaje metody jako metody klasy.

module Bar def hello p 'hello' endendclass Foo extend BarendFoo.hello # no .new!# => 'hello'

prepend

oprócz include/extend, Ruby 2.0+ dodaje metodę prependprepend jest podobny do include, ale zamiast tego wstawia moduł przed klasą include w łańcuchu dziedziczenia.

class Foo include Bar prepend BazendFoo.ancestors#=> 

w Rubim możesz ponownie otworzyć dowolną klasę i przedefiniować metody na niej-nie wydaje się przydatne nadpisywanie metod na klasie za pomocą preparowanego modułu, w przeciwieństwie do przedefiniowania ich. prepend przydaje się wtedy, gdy nadal potrzebujesz oryginalnej implementacji metody, ponieważ preparowane moduły mogą nadpisywać metody, ale nadal używają super, aby wywołać oryginalną implementację.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.