In-depth Ruby: Modules & Include vs. Extend

Ruby biedt een constructie genaamd Module wat een soort dunne klasse is. Op het eerste, Ruby devs zou kunnen kijken naar Modules als een “junk lade” van code die gewoon rond gegooid en gebruikt om bestanden te organiseren, maar er is een methode om deze waanzin. De Ruby klasse Class erft van Module en voegt dingen toe zoals instantiation, properties, etc – alles wat je normaal zou denken dat een klasse zou hebben. Omdat Module letterlijk een voorouder is van Class, betekent dit dat Modules op sommige manieren als klassen kunnen worden behandeld.

het belangrijkste om te begrijpen is hoe de Ruby voorouder keten werkt. Zoals alle OOP talen, Ruby ondersteunt erfenis. Wanneer je erft van een klasse, wordt de superklasse toegevoegd aan je voorouder keten. U kunt de voorouders van elke klasse bekijken door ancestors op te roepen:

class Foo < BarendFoo.ancestors#=> 

zoals vermeld, kunt u Module vinden in de array Class.ancestors.

wanneer u include een module in uw klasse toevoegt, wordt de module toegevoegd aan de voorouderketen van uw klasse – net als een klasse. Dit maakt include gewoon een vorm van overerving, er is niets speciaals aan.

module Barendclass Foo include BarendFoo.ancestors#=> 

alle methoden in Bar worden toegevoegd aan Foo als instantiemethoden. Omdat Bar zich in de keten bevindt, kunt u zelfs super van daaruit aanroepen om methoden daarboven in de keten aan te roepen, of ze nu gedefinieerd zijn op Modules of klassen.

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

hoewel Bar een module is, roept super nog steeds de keten aan en wordt Baz#hello ook genoemd. Het is vermeldenswaard dat Bar wordt toegevoegd aan de voorouderketen voor Baz. Wanneer een module is opgenomen, wordt het altijd direct toegevoegd bovenop het Inclusief klasse. Dit kan verwarrend worden bij het toevoegen van meerdere modules, omdat ze zijn opgenomen in “omgekeerde” volgorde:

class Foo include A include BendFoo.ancestors#=> 

wanneer A is opgenomen, wordt het direct boven Fooingevoegd. Maar als B is opgenomen, wordt het ook direct boven Foo ingevoegd, zodat het eindigt vóór A.

include vs extend

include is gemakkelijk genoeg om te begrijpen, het voegt de methoden van de module als instantie methoden aan het Inclusief klasse. U kunt denken aan extend die hetzelfde doet, maar in plaats daarvan de methoden toevoegen als klassenmethoden.

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

prepend

naast include/extend voegt Ruby 2.0+ de prepend methode toe. prepend is vergelijkbaar met include, maar voegt in plaats daarvan de module in voor de inclusief-klasse in de overerving-keten.

class Foo include Bar prepend BazendFoo.ancestors#=> 

in Ruby kunt u elke klasse opnieuw openen en de methoden daarop opnieuw definiëren-het lijkt niet nuttig om methoden op een klasse te overschrijven met behulp van een vooraf ingestelde module in tegenstelling tot ze opnieuw te definiëren. Waar prepend van pas komt is wanneer u nog steeds de oorspronkelijke implementatie van de methode nodig hebt, omdat vooraf ingestelde modules methoden kunnen overschrijven, maar nog steeds super gebruiken om de oorspronkelijke implementatie aan te roepen.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.