Ruby gir en konstruksjon kalt en Module
som er liksom som en tynn Klasse. Først Kan Ruby devs se På Moduler som En» søppelskuff » med kode som bare kastes rundt og brukes til å organisere filer, men det er en metode for denne galskapen. Ruby-klassenClass
arver fra Module
og legger til ting som instantiering, egenskaper, etc-alle ting du normalt ville tro en klasse ville ha – Fordi Module
er bokstavelig talt en forfedre av Class
, betyr Dette At Moduler kan behandles som klasser på noen måter.
Viktigst å forstå er hvordan Ruby stamfar kjeden fungerer. Som alle oop-språk støtter Ruby arv. Når du arver fra en klasse, legges superklassen til i stamfarskjeden din. Du kan se forfedrene til enhver klasse ved å ringe ancestors
på den:
class Foo < BarendFoo.ancestors#=>
som nevnt kan du finne Module
i matrisen Class.ancestors
.
Når du include
en modul i klassen din, blir modulen lagt til klassens forfederkjede – akkurat som en klasse. Dette gjør include
bare en form for arv, det er ikke noe spesielt med det.
module Barendclass Foo include BarendFoo.ancestors#=>
alle metodene iBar
legges til Foo
som instansmetoder. Fordi Bar er i kjeden, kan du til og med ringe super
fra det å ringe metoder over det i kjeden, enten de er definert 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
selv omBar
er en modul,super
ringer fortsatt opp kjeden og såBaz#hello
kalles også. Det er verdt å merke seg at Bar
legges til forfedrekjeden foran Baz. Når en modul er inkludert, er det alltid lagt direkte på toppen av det er inkludert klasse. Dette kan bli forvirrende når du legger til flere moduler, siden de er inkludert i «omvendt» rekkefølge:
class Foo include A include BendFoo.ancestors#=>
når A
er inkludert, settes den inn direkte over Foo
. Men når B
er inkludert, er det også satt inn direkte over Foo
, så det ender opp landing før A
.
include vs extend
include
er lett nok å forstå, det legger modulens metoder som instans metoder til det er inkludert klasse. Du kan tenke på extend
gjør det samme, men i stedet legger metodene som klassemetoder.
module Bar def hello p 'hello' endendclass Foo extend BarendFoo.hello # no .new!# => 'hello'
prepend
I tillegg til å inkludere / utvide, Legger Ruby 2.0+ tilprepend
– metoden. prepend
ligner på include
, men setter i stedet inn modulen før inkludert-klassen i arvskjeden.
class Foo include Bar prepend BazendFoo.ancestors#=>
I Ruby kan du åpne hvilken som helst klasse og omdefinere metodene på Den-det virker ikke nyttig å overstyre metoder på en klasse ved hjelp av en forhåndsdefinert modul i motsetning til å omdefinere dem. Hvorprepend
kommer til nytte er når du fortsatt trenger den opprinnelige implementeringen av metoden, fordi forhåndsdefinerte moduler kan overstyre metoder, men fortsatt bruke super
for å ringe den opprinnelige implementeringen.