in-Depth Ruby: Modules & Include vs.Extend

A Ruby egy Module nevű konstrukciót biztosít, amely olyan, mint egy vékony osztály. Először a Ruby devs olyan modulokat nézhet, mint egy kód “szemétfiókja”, amelyet csak a fájlok rendezésére használnak, de van egy módszer erre az őrületre. A Ruby osztályClass örökli aModule és hozzáad dolgokat, mint például példányosítás, tulajdonságok, stb – minden dolog, amit általában gondolnánk egy osztály volna. Mivel a Moduleszó szerint aClass őse, ez azt jelenti, hogy a modulok bizonyos szempontból osztályokként kezelhetők.

a legfontosabb megérteni, hogyan működik a Ruby őslánc. Mint minden OOP nyelv, a Ruby is támogatja az öröklést. Amikor egy osztályból örököl, a szuperosztály hozzáadódik az őslánchoz. Bármely osztály őseit megtekintheti a ancestors hívásával rajta:

class Foo < BarendFoo.ancestors#=> 

mint említettük, megtalálható Module a tömbben Class.ancestors.

amikor include egy modult az osztályába, a modul hozzáadódik az osztály ősláncához – akárcsak egy osztály. Ez teszi a include csak az öröklés egyik formáját, nincs benne semmi különös.

module Barendclass Foo include BarendFoo.ancestors#=> 

a Barösszes metódusa hozzáadódik a Foo példány metódusként. Mivel a Bar a láncban van, akkor is hívhat super belőle a fenti módszerek meghívására a láncban, függetlenül attól, hogy modulokon vagy osztályokon vannak-e meghatározva.

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

annak ellenére, hogy Baregy modul, supermég mindig felhívja a láncot, így Baz#hello is nevezik. Érdemes megjegyezni, hogy Bar hozzáadódik a BAZ előtti őslánchoz. Ha egy modult tartalmaz,akkor mindig közvetlenül hozzáadódik az osztályhoz. Ez zavaró lehet több modul hozzáadásakor, mivel ezek “fordított” sorrendben vannak:

class Foo include A include BendFoo.ancestors#=> 

Ha a Atartalmazza, akkor közvetlenül a Foo fölé kerül. De amikor a Bszerepel, akkor közvetlenül aFoofölé is beillesztésre kerül, így végül aA előtt landol.

include vs extend

include elég könnyű megérteni, hozzáadja a modul módszereit példány metódusként az osztályhoz. Gondolhat arra, hogy extend ugyanazt csinálja, hanem a metódusokat osztály metódusként adja hozzá.

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

prepend

Az include/extend mellett a Ruby 2.0+ hozzáadja aprepend módszert. prepend hasonló a include – hez, de ehelyett beszúrja a modult az including osztály elé az öröklési láncban.

class Foo include Bar prepend BazendFoo.ancestors#=> 

A Ruby-ban bármely osztályt újra megnyithat, és újradefiniálhatja a rajta lévő metódusokat – nem tűnik hasznosnak az osztály metódusainak felülbírálása egy előregyártott modul használatával, szemben az újradefiniálással. Ahol aprepend akkor hasznos, ha még mindig szüksége van a módszer eredeti megvalósítására, mert az előregyártott modulok felülbírálhatják a módszereket, de továbbra is használjáksuper az eredeti megvalósítás meghívásához.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.