Ruby har en hendig og praktisk måte å dele instansvariabler på ved hjelp av nøkler som
attr_accessor :var
attr_reader :var
attr_writer :var
Hvorfor skulle jeg velge attr_reader
eller attr_writer
hvis jeg bare kan bruke attr_accessor
? Er det noe med ytelsen (noe jeg tviler på)? Jeg antar at det er en grunn, ellers ville de ikke ha laget slike nøkler.
Du kan bruke de ulike tilgangene til å kommunisere hensikten din til noen som leser koden din, og gjøre det enklere å skrive klasser som fungerer korrekt uansett hvordan deres offentlige API kalles.
class Person
attr_accessor :age
...
end
Her ser jeg at jeg både kan lese og skrive alderen.
class Person
attr_reader :age
...
end
Her ser jeg at jeg bare kan lese alderen. Tenk deg at den settes av konstruktøren til denne klassen og deretter forblir konstant. Hvis det fantes en mutator (writer) for alder, og klassen var skrevet ut fra at alderen ikke endres når den først er satt, ville det kunne oppstå en feil hvis koden kalte mutatoren.
Men hva skjer bak kulissene?
Hvis du skriver:
attr_writer :age
blir det oversatt til:
def age=(value)
@age = value
end
Hvis du skriver:
attr_reader :age
blir det oversatt til:
def age
@age
end
Hvis du skriver:
attr_accessor :age
blir det oversatt til:
def age=(value)
@age = value
end
def age
@age
end
Når du vet det, kan du tenke på det på en annen måte: Hvis du ikke hadde attr_...-hjelperne og måtte skrive tilgangene selv, ville du da skrevet flere tilganger enn det klassen din trengte? Hvis du for eksempel bare trengte å lese alder, ville du da også skrevet en metode for å skrive den?
Ikke alle attributtene til et objekt er ment å kunne angis direkte fra utsiden av klassen. Å ha forfattere for alle instansvariabler er vanligvis et tegn på svak innkapsling og en advarsel om at du introduserer for mye kobling mellom klassene dine.
Et praktisk eksempel: Jeg skrev et designprogram der du legger elementer i containere. Elementet hadde attr_reader :container
, men det ga ikke mening å tilby en writer, siden den eneste gangen elementets container skal endres er når det plasseres i en ny, noe som også krever posisjoneringsinformasjon.
Det er ikke alltid du ønsker at instansvariablene dine skal være fullt tilgjengelige fra utsiden av klassen. Det er mange tilfeller der det er fornuftig å tillate lesetilgang til en instansvariabel, men kanskje ikke skrivetilgang (f.eks. en modell som henter data fra en skrivebeskyttet kilde). Det finnes tilfeller der du ønsker det motsatte, men jeg kan ikke komme på noen som ikke er konstruerte på stående fot.