7. Methodes
7.1 Hoe bepaald Ruby welke methode moet worden uitgevoerd?
Alle messages aan methodes worden in Ruby dynamisch gebonden. Het
zoekt eerst naar singleton methodes in de ontvanger,daarna naar
methodes die gedefineerd zijn in de klasse van de ontvanger en
tenslotte naar methodes die gedefinieerd zijn in de superklassen van de
ontvanger (inclusief in eventuele mix-in modules). Je kan de
zoekvolgorde zichtbaar maken met Classname.ancestors
, die
de superklassen en en modules van ClassName
toont.
Word er ggen methode gevonden dan probeerd Ruby de methode method_missing
te vinden. Deze methode maakt het mogelijk om messages aan onbekende
methodes af te handelen en word vaak gebruikt om klassen een dynamische
interface te geven.
module Indexed |
Dit programma geeft niet, zoals je zou verwachten "b\n" terug, maar
10. Wanneer naar de methode []
word gezocht word ze
gevonden in de klasse String
, voordat Indexed
word doorzocht. Je moet [] rechtstreeks in de klasse String
herdefinieeren.
7.2 Zijn +
, -
, *
... operators?
+
, -
, etc. zijn geen operators maar
methode aanroepen. Het is dus mogelijk om ze te overloaden met nieuwe
definities.
class MyString < String |
Onderstaande zaken echter, zijn ingebouwde control structuren en geen methodes. Het is dus miet mogelijk om ze te overloaden.
=, .., ..., !, not, ||, &&, and, or, :: |
Om unaire operators te overloaden of te definieeren moet je +@
en -@
als methode namen gebruiken.
=
word gebruikt om een methode te definieeren die aan
een attribuut van een object een waarde toekent:
class Test |
Als operators zoals +
en -
zijn
gedefinieerd regelt Ruby automatisch de self assignment vormen (+=
,-=
etc.).
7.3 Waar zijn ++
and --
?
Ruby heeft geen autoincrement and autodecrement operators. Gebruik
in plaats daarvan += 1
of -= 1
.
7.4 Al die objecten zijn prima, maar heeft Ruby ook gewone functies?
Ja en nee. Ruby heeft methodes die lijken op functies in talen zoals C of Perl:
def writeln(str) |
Dit zijn echter methode aanroepen zonder ontvanger. In dat geval
gaat Ruby ervan uit dat de ontvanger self
is.
Dus, writeln
lijkt op een functie maar is in
werkelijkheid een methode van de klasse Object
en die
gestuurd wordt naar de ontvanger self
. Ruby is een pure
object-georienteerde taal.
Natuurlijk kan je zulke methodes gebruiken als of het functies zijn.
7.5 Waar komen al die op functies lijkende methodes vandaan?
Alle klassen in ruby hebben Object
als superklasse. De
definitie van de klasse Object
bevat een mix-in van de
methodes die gedefinieerd zijn in de Kernel
module. Deze
methodes zijn daarom beschikbaar binnen elk object in het systeem.
Zelfs als je een simpel ruby programma schrijft zonder klassen werk
je in werkelijkheid binnen de klasse Object
.
7.6 Kan ik toegang krijgen tot de instance variabelen van een object?
De instance variabelen (de variabelen wiens naam met @ begint) van
een object zijn niet direct toegankelijk buiten het object. Dit
bevorderd goede encapsulation. Ruby maakt het gemakkelijk om accessors
voor deze variabelen te definieren zodat ze te gebruiken zijn als
of het attributen betreft. Het enige dat je hoeft te doen is attr_reader
,attr_writer
,
or attr_accessor
te gebruiken.
class Person |
Je kan ook je eigen accessor functies definieeren (bijvoorbeeld om
validatie of afgeleide attribute te implementeren). De read accessor is
gewoon een methode zonder parameters en de toekennings accessor een
methode die eindigd op =, die een enkele parameter heeft. Hoewel er
geen spatie is toegestaan tussen de methodenaam en de = in de methode
definitie is een spatie wel toegestaan bij de methode aanroep
zodat ze lijkt op een normake toekenning. Je kan self assignments zoals
+=
en -=
gebruiken, als de corresponderende +
or -
methoeds zijn gedefinieerd.
7.7 Wat is het verschil tussen private
en protected
?
Het keyword zordt ervoor dat een methode alleen in functie
vorm kan worden aangeroepen. De ontvanger kan dus alleen self
zijn. Een private methode is alleen aan te roepen vanuit de klasse
waarin ze is gedefineerd of in een van diens subklassen.
class Test |
Protected methodes zijn ook alleen maar aante roepen vanuit de klasse waarin ze is gedefineerd of in een van diens subklassen, maar ze kunnen met een ontvanger worden aangeroepn. Bijvoorbeeld:
def <=>(other) |
Dit compileert als age
een protected methode is, maar
niet wanneer ze private is.
Dit alles helpt je om het binnenwerk van je klassen af te schermen.
7.8 Hoe kan ik de zichtbaarheid van een methode veranderen?
De zichtbaarheid van methodes kan worden veranderd doorde keywords private
,protected
of public
te gebruiken. Wanneer ze zonder parameters
gebruikt worden veranderen ze de zichtbaarheid van de na het keyword
gedefinieerde methodes. Gebruikt met parameters veranderen ze de
zichtbaarheid van de genoemde methodes.
class Foo |
e kan een klasse methode private maken met de private_class_method
e.
class Foo |
De standaard zichtbaarheid voor methodes is public. De einige
uitzondering is de instance initializatie methode, initialize
.
Methodes die buiten een klasse zijn gedefinieerd zijn ook standaard public.
7.9 Kan een identifier die begint met een hoofdletter de naam van een methode zijn?
Ja, maar denk er goed over na voordat je dit doet.Als Ruby een naam met
een hoofdletter ziet gevolgd door een spatie zal ze er in het algemeen
van uitgaan dat het gaat om een constante i.p.v. om een mothode. Gebuik
je methodenamen met hoofdletters dan moet je er aan denken om altijd de
parameters tussen haakjes te zetten en het openingshaakje direct na de
methodenaam te plaatsen (dit laatste is zo wie zo een goed idee).
7.10 Het aanroepen van super
geeft eenArgumentError!
Het aanroepen van super
zonder parameters in een
methode geeft alle parameters van die methode door aan een methode met
die zelfde naam in een superklasse. Als het aantal paramters van de
oorspronkelijke methode afwijkt van die uit de hoger liggende klasse
word een ArgumentError
veroorzaakt. Om dit te voorkomen
moet je super
aanroepen met het juiste aantal parameters.
7.11 Hoe roep ik een methode aan met dezelfde naam maar twee niveau's hoger?
super
roept een methode met de zelfde naam op die een
niveau hoger ligt. Als je een methode overload die meer dan een niveau
hoger ligt moet je alias
gebruiken om die een nieuwe naam
te geven voordat je die maskeerd met je methode definitie. De oude
methode is dan aan te roepen via de alias.
7.12 Hoe roep ik een ingebouwde methode aan nadat ik haar geherdefinieerd heb?
Binnen de methode definitie kan je super
gebruiken. Je
kan ook alias
gebruiken om haar een alternatieve naam te
geven. Tenslotte kan je de oorspronkelijke methode aanroepen als een
singleton methode vanKernel
.
7.13 Wat is een destructive methode?
Een destructieve methode is een methode die de staat van een object
wijzigd. String, Array, Hash en andere klassen hebben zulke methodes.
Vaak zijn er twee versies van een methode, een met een normale naam, en
een met dezelfde naam gevolgd door een !
. De normale
versie maakt een kopie van de ontvanger, voert de verandering uit en
geeft de kopie terug. De versie met het ! veranderd de ontvaanger zelf.
Let er op dat er een behoorlijk aantal destructieve methodes is die
geen ! hebben, bijvoorbeeld: toekennings operators (name=
),
array toekenning ([]=
), en methodes zoals Array.delete
.
7.1Waarom kunnen destructieve methodes gevaarlijk zijn?}
Bedenk dat toekenning over het algemeen kopieen van object referenties maakt en dat het doorgeven van parameters equivalent is met toekenning. Dit betekend dat je meerdere variabelen kan krijgen die verwijzen naar het zelfde object. Als een van die variabelen gebruikt wordt in een destructieve methode zal het object waarnaar de andere variabelen verwijzen dus wijzigen.
def foo(str) |
In dit geval is de actuele parameter gewijzigd.
7.15 Kan een methode meerdere waardes teruggeven?
Ja en nee.
def m1 |
Dus, er word maar een iets teruggegeven, maar dat iets kan een complex object zijn. In het geval van arrays kan je meervoudige toekenningen gebruiken om het effect van meervoudige return waardes te krijgen. Bijvoorbeeld:
def foo |