syvällinen Ruby: Modules & Include vs. Extend

Ruby tarjoaa Konstruktion nimeltä Module, joka on tavallaan kuin ohut Luokka. Aluksi Ruby devs saattaa tarkastella moduuleja kuin ”roskalaatikkoa” koodia, jota vain heitetään ympäriinsä ja käytetään tiedostojen järjestämiseen, mutta tälle hulluudelle on olemassa menetelmä. Rubiiniluokka Class perii Module ja lisää siihen instantiaatiota, ominaisuuksia jne. – kaikkea, mitä luokalla normaalisti luulisi olevan. Koska Module on sananmukaisesti Class esi-isä, tämä tarkoittaa, että moduuleja voidaan käsitellä tietyllä tavalla luokkina.

tärkeintä on ymmärtää, miten rubiinin esi-isäketju toimii. Kuten kaikki OOP-kielet, Ruby tukee periytymistä. Kun perii luokalta, superluokka lisätään esi-isien ketjuun. Minkä tahansa luokan esi-isiä voi tarkastella kutsumalla ancestors sillä:

class Foo < BarendFoo.ancestors#=> 

kuten mainittu, Module array Class.ancestors.

kun include moduuli omaan luokkaan, moduuli lisätään oman luokan esi – isäketjuun-aivan kuten luokkakin. Tämä tekee include vain eräänlaisen perinnön, siinä ei ole mitään erikoista.

module Barendclass Foo include BarendFoo.ancestors#=> 

kaikki Bar lisätään Foo instanssimenetelmiksi. Koska Bar on ketjussa, voit jopa kutsua super siitä kutsumenetelmiä sen yläpuolella ketjussa, olivatpa ne määritelty moduuleilla tai luokilla.

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

vaikka Bar on moduuli, super kutsuu edelleen ketjua ylös ja niin Baz#hello on myös ns. On syytä huomata, että Bar lisätään Bazin edessä olevaan kantaketjuun. Kun moduuli on mukana, se lisätään aina suoraan päälle se sisältää luokan. Tämä voi saada sekava lisättäessä useita moduuleja, Koska ne sisältyvät ”Käänteinen” järjestyksessä:

class Foo include A include BendFoo.ancestors#=> 

kun A lasketaan mukaan, se lisätään suoraan Foo. Mutta kun B lasketaan mukaan, se lisätään myös suoraan Foo, joten se päätyy laskuun ennen A.

include vs extend

include on riittävän helppo ymmärtää, se lisää moduulin menetelmät instanssimenetelminä sen sisältämään luokkaan. Voi ajatella, että extend tekisi saman asian, mutta sen sijaan lisäisi menetelmät luokkamenetelmiksi.

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

prepend

include/extendin lisäksi Ruby 2.0+ lisää prepend metodin. prepend on samankaltainen kuin include, mutta lisää sen sijaan moduulin perintöketjussa olevan including-luokan eteen.

class Foo include Bar prepend BazendFoo.ancestors#=> 

Rubyssa voi avata minkä tahansa luokan uudelleen ja määritellä sen menetelmät uudelleen-ei tunnu hyödylliseltä ohittaa luokan menetelmiä prependoidulla moduulilla sen sijaan, että ne määriteltäisiin uudelleen. Missä prepend tulee kätevä on silloin, kun tarvitaan vielä menetelmän alkuperäistä toteutusta, koska prependoidut moduulit voivat ohittaa menetelmät, mutta käyttävät silti super kutsua alkuperäistä toteutusta.

Vastaa

Sähköpostiosoitettasi ei julkaista.