In-Depth Ruby: Modules & Include vs. Extend

Ruby fornisce un costrutto chiamatoModule che è un po ‘ come una classe sottile. All’inizio, gli sviluppatori di Ruby potrebbero guardare i moduli come un ” cassetto spazzatura” di codice che viene appena gettato in giro e utilizzato per organizzare i file, ma c’è un metodo per questa follia. La classe RubyClass eredita daModule e aggiunge cose come istanziazione, proprietà, ecc. Poiché Module è letteralmente un antenato di Class, ciò significa che i moduli possono essere trattati come classi in qualche modo.

La cosa più importante da capire è come funziona la catena degli antenati di Ruby. Come tutti i linguaggi OOP, Ruby supporta l’ereditarietà. Quando si eredita da una classe, la superclasse viene aggiunta alla catena antenato. È possibile visualizzare gli antenati di qualsiasi classe chiamando ancestors su di esso:

class Foo < BarendFoo.ancestors#=> 

Come accennato, è possibile trovare Module nell’array Class.ancestors.

Quando si include un modulo nella classe, il modulo viene aggiunto alla catena antenato della classe – proprio come una classe. Questo rende include solo una forma di ereditarietà, non c’è nulla di speciale.

module Barendclass Foo include BarendFoo.ancestors#=> 

Tutti i metodi inBarvengono aggiunti aFoo come metodi di istanza. Poiché Bar è nella catena, puoi anche chiamare super da esso per chiamare i metodi sopra di esso nella catena, indipendentemente dal fatto che siano definiti su Moduli o Classi.

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

Anche seBarè un modulo,superrichiama ancora la catena e quindi viene chiamato ancheBaz#hello. Vale la pena notare che Bar viene aggiunto alla catena antenata di fronte a Baz. Quando un modulo è incluso, viene sempre aggiunto direttamente in cima alla sua classe inclusa. Questo può diventare confuso quando si aggiungono più moduli, poiché sono inclusi nell’ordine “inverso”:

class Foo include A include BendFoo.ancestors#=> 

QuandoAè incluso, viene inserito direttamente sopraFoo. Ma quandoB è incluso, viene inserito anche direttamente sopraFoo, quindi finisce per atterrare prima diA.

include vs extend

include è abbastanza facile da capire, aggiunge i metodi del modulo come metodi di istanza alla sua classe inclusa. Puoi pensare aextend facendo la stessa cosa, ma aggiungendo invece i metodi come metodi di classe.

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

antepone

Oltre a includere/estendere, Ruby 2.0+ aggiunge il metodo prependprependè simile ainclude, ma inserisce invece il modulo prima della classe including nella catena di ereditarietà.

class Foo include Bar prepend BazendFoo.ancestors#=> 

In Ruby puoi riaprire qualsiasi classe e ridefinire i metodi su di essa-non sembra utile sovrascrivere i metodi su una classe usando un modulo anteposto invece di ridefinirli. Doveprepend è utile quando hai ancora bisogno dell’implementazione originale del metodo, perché i moduli anteposti possono sovrascrivere i metodi ma usano ancorasuper per chiamare l’implementazione originale.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.