in-Depth Ruby: Modules & Include vs. Udvid

Ruby giver en konstruktion kaldet a Module som er lidt som en tynd klasse. I første omgang kan Ruby devs se på moduler som en” junk skuffe ” af kode, der bare smides rundt og bruges til at organisere filer, men der er en metode til denne vanvid. Ruby-klassen Class arver fra Module og tilføjer ting som instantiation, egenskaber osv. – alle ting, du normalt ville tro, at en klasse ville have. Fordi Module er bogstaveligt talt en forfader til Class, betyder det, at moduler kan behandles som klasser på nogle måder.

det vigtigste at forstå er, hvordan Ruby ancestor-kæden fungerer. Som alle OOP-sprog understøtter Ruby arv. Når du arver fra en klasse, tilføjes superklassen til din forfædrekæde. Du kan se forfædrene til enhver klasse ved at ringe ancestors på den:

class Foo < BarendFoo.ancestors#=> 

Som nævnt kan du findeModulei arrayetClass.ancestors.

Når du include et modul i din klasse, tilføjes modulet til din klasses forfædrekæde – ligesom en klasse. Dette gør include bare en form for arv, der er ikke noget særligt ved det.

module Barendclass Foo include BarendFoo.ancestors#=> 

alle metoderne i Bartilføjes til Foo som instansmetoder. Fordi Bar er i kæden, kan du endda ringe super fra det for at kalde metoder over det i kæden, uanset om de er defineret på moduler eller klasser.

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

selvomBarer et modul,superkalder stadig kæden og såBaz#hello kaldes også. Det er værd at bemærke, at Bar tilføjes til forfædrekæden foran base. Når et modul er inkluderet, tilføjes det altid direkte oven på det inklusive klasse. Dette kan blive forvirrende, når du tilføjer flere moduler, da de er inkluderet i” omvendt ” rækkefølge:

class Foo include A include BendFoo.ancestors#=> 

NårAer inkluderet, indsættes den direkte overFoo. Men når B er inkluderet, indsættes den også direkte over Foo, så det ender med at lande før A.

Inkluder vs Udvid

include er let nok at forstå, det tilføjer modulets metoder som instansmetoder til det inklusive klasse. Du kan tænke på extend gør det samme, men i stedet tilføjer metoderne som klassemetoder.

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

prepend

ud over at inkludere/udvide tilføjer Ruby 2.0+prepend metode. prepend ligner include, men indsætter i stedet modulet før den inkluderende klasse i arvskæden.

class Foo include Bar prepend BazendFoo.ancestors#=> 

i Ruby kan du genåbne enhver klasse og omdefinere metoderne på den-det synes ikke nyttigt at tilsidesætte metoder på en klasse ved hjælp af et forudindstillet modul i modsætning til at omdefinere dem. Hvor prepend kommer godt med, er, når du stadig har brug for den oprindelige implementering af metoden, fordi forudindstillede moduler kan tilsidesætte metoder, men stadig bruger super for at kalde den oprindelige implementering.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.