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.