Titta på någon objektorienterad kod och allt mer eller mindre följer samma mönster. Skapa ett objekt, ring några metoder på det objektet och åtkomstattribut för det objektet. Det finns inte mycket annat du kan göra med ett objekt förutom att skicka det som en parameter till ett annat objekts metod. Men det vi är upptagen med här är attribut.
Attribut är som instansvariabler du kan komma åt via objektdotnotationen. Till exempel, person.name skulle komma åt en persons namn. På liknande sätt kan du ofta tilldela attribut som person.name = "Alice". Detta är en liknande funktion som medlemsvariabler (som i C ++), men inte riktigt samma. Det finns inget speciellt här, attribut implementeras på de flesta språk med "getters" och "setters", eller metoder som hämtar och ställer in attributen från instansvariabler.
Ruby gör ingen skillnad mellan attributgetter och -sättare och normala metoder. På grund av Rubys flexibla metod som kallar syntax behöver ingen skillnad göras. Till exempel, person.name och
person.name () är samma sak, du ringer till namn metod med nollparametrar. Den ena ser ut som ett metodsamtal och den andra ser ut som ett attribut, men de är verkligen båda samma sak. De kallar båda bara för namn metod. På samma sätt kan alla metodnamn som slutar i ett likhetstecken (=) användas i en uppgift. Påståendet person.name = "Alice" är verkligen samma sak som person.name = (alice), även om det finns ett mellanrum mellan attributnamnet och likhetstecknet, ringer det fortfarande bara name = metod.Du kan enkelt implementera attribut själv. Genom att definiera setter- och getter-metoder kan du implementera alla attribut du önskar. Här är några exempelkoder som implementerar namn attribut för en personklass. Det lagrar namnet i en @namn instansvariabel, men namnet behöver inte vara detsamma. Kom ihåg att det inte finns något speciellt med dessa metoder.
En sak du kommer att märka direkt är att det här är mycket arbete. Det är mycket att skriva bara för att säga att du vill ha ett attribut som heter namn som får åtkomst till @namn instansvariabel. Lyckligtvis tillhandahåller Ruby några bekvämlighetsmetoder som kommer att definiera dessa metoder för dig.
Det finns tre metoder i Modul klass som du kan använda inuti dina klassdeklarationer. Kom ihåg att Ruby inte gör någon åtskillnad mellan runtime och "compile time", och att någon kod i klassdeklarationerna inte bara kan definiera metoder utan även samtalsmetoder. Ringer till attr_reader, attr_writer och attr_accessor metoder kommer i sin tur att definiera de bosättare och brev som vi definierade oss i föregående avsnitt.
De attr_reader metoden gillar precis som det låter som den kommer att göra. Den tar valfritt antal symbolparametrar och definierar för varje parameter en "getter" -metod som returnerar instansvariabeln med samma namn. Så vi kan ersätta vår namn i föregående exempel med attr_reader: namn.
På samma sätt attr_writer metoden definierar en "setter" -metod för varje symbol som skickas till den. Observera att jämntecknet inte behöver vara en del av symbolen, bara attributnamnet. Vi kan ersätta name = metod från föregående exempel med ett samtal till attr_writier: namn.
Och som förväntat attr_accessor gör jobbet för båda attr_writer och attr_reader. Om du behöver både en setter och getter för ett attribut är det vanligt att inte ringa de två metoderna separat och istället ringa attr_accessor. Vi kan ersätta både de namn och name = metoder från föregående exempel med ett enda samtal till attr_accessor: namn.
Varför ska du definiera inställare manuellt? Varför inte använda attr_ * metoder varje gång? Eftersom de bryter inkapsling. Inkapsling är det huvudsakliga som säger att ingen extern enhet ska ha obegränsad tillgång till ditt interna tillstånd objekt. Allt ska nås med ett gränssnitt som förhindrar användaren från att skada objektets interna tillstånd. Med hjälp av metoderna ovan har vi stansat ett stort hål i vår inkapslingsvägg och tillät absolut att allt ställs in för ett namn, även uppenbarligen ogiltiga namn.
En sak du ofta ser är att attr_reader kommer att användas för att snabbt definiera en getter, men en anpassad setter definieras eftersom det interna tillståndet för objektet ofta vill vara läsa direkt från det interna tillståndet. Sättaren definieras sedan manuellt och kontrollerar för att säkerställa att värdet som ställs in är vettigt. Eller, kanske oftare, definieras ingen setter alls. De andra metoderna i klassfunktionen ställer instansvariabeln bakom gettern på något annat sätt.
Vi kan nu lägga till en ålder och korrekt implementera a namn attribut. De ålder attribut kan ställas in i konstruktormetoden, läs med hjälp av ålder getter men bara manipuleras med hjälp av have_birthday metod, som kommer att öka åldern. De namn attribut har en normal getter, men setteren ser till att namnet är aktiverat och är i form av Förnamn Efternamn.