Sunt având un timp de greu de înțelegere `attr_accessor în Ruby. Poate cineva să-mi explice asta?
Las's spun ai o clasa de "Persoană".
class Person
end
person = Person.new
person.name # => no method error
Evident, nu am definit metoda "nume". Las's fac asta.
class Person
def name
@name # simply returning an instance variable @name
end
end
person = Person.new
person.name # => nil
person.name = "Dennis" # => no method error
Aha, putem citi numele, dar asta nu't înseamnă că puteți atribui nume. Acestea sunt două metode diferite. Primul este numit cititor și acesta este numit scriitor. Ne-am't crea scriitor și totuși atât de las's fac asta.
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"
Minunat. Acum putem scrie și să citească de exemplu, variabila @nume
folosind cititor și scriitor metode. Cu excepția, acest lucru este făcut atât de des, de ce să pierzi timpul scriind aceste metode de fiecare dată? Putem face asta mai ușor.
class Person
attr_reader :name
attr_writer :name
end
Chiar și acest lucru poate deveni repetitive. Atunci când doriți atât cititor și scriitor folosi doar accesor!
class Person
attr_accessor :name
end
person = Person.new
person.name = "Dennis"
person.name # => "Dennis"
Funcționează în același mod! Și ghici ce: de exemplu, variabila `@nume în persoana noastră obiect va fi setat la fel ca atunci când am făcut-o manual, astfel încât să puteți folosi în alte metode.
class Person
attr_accessor :name
def greeting
"Hello #{@name}"
end
end
person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"
Ca's a. În scopul de a înțelege cum attr_reader,
attr_writer", și " attr_accessor metodele de fapt de a genera metode pentru tine, citeste alte răspunsuri, cărți, ruby docs.
attr_accessor e o metodă. (Link-ul ar trebui să ofere o perspectivă mai mult cu cât acesta funcționează - uită-te la perechi de metode generate, și un tutorial ar trebui să-ți arăt cum să-l folosească.)
Trucul este că "clasa" este nu este o definiție în Ruby (este "o definiție" în limbaje cum ar fi C++ și Java), dar este o expresie care evaluează*. Este în această evaluare atunci când attr_accessor
metoda este invocată, care la rândul lor modifică actuala clasă - amintiți-vă implicit receptor: de sine.attr_accessor
, unde "sinele" este "open" obiect de clasă la acest punct.
Nevoia de `attr_accessor și prieteni, este, ei bine:
Ruby, cum ar fi Smalltalk, nu permite variabile de instanta pentru a fi accesate în afara de metodele1 pentru acel obiect. Care este, de exemplu, variabilele nu pot fi accesate în anii x.y
formă așa cum este comună în, să zicem, Java sau chiar Python. În Ruby " y " este întotdeauna luată ca un mesaj pentru a trimite (sau "metodă de a apela"). Astfel attr_*
metode de a crea ambalaje care proxy de exemplu `@variabilă de acces prin dinamic creat metode.
Șabloane de rahat
Sper că acest lucru clarifică unele din cele mai mici detalii. Fericit de codificare.
1 nu't strict adevărat și acolo sunt unii "tehnici" în jurul thisdar nu există nici un suport pentru sintaxa "publică variabilă de exemplu" de acces.
attr_accessor
este (ca @pst declarat) doar o metodă. Ceea ce face este de a crea mai multe metode pentru tine.
Deci acest cod aici:
class Foo
attr_accessor :bar
end
este echivalent cu acest cod:
class Foo
def bar
@bar
end
def bar=( new_value )
@bar = new_value
end
end
Puteți scrie acest tip de metodă în Ruby:
class Module
def var( method_name )
inst_variable_name = "@#{method_name}".to_sym
define_method method_name do
instance_variable_get inst_variable_name
end
define_method "#{method_name}=" do |new_value|
instance_variable_set inst_variable_name, new_value
end
end
end
class Foo
var :bar
end
f = Foo.new
p f.bar #=> nil
f.bar = 42
p f.bar #=> 42
Este doar o metodă care definește metodele getter si setter pentru variabile de instanta. Un exemplu de implementare ar fi:
def self.attr_accessor(*names)
names.each do |name|
define_method(name) {instance_variable_get("@#{name}")} # This is the getter
define_method("#{name}=") {|arg| instance_variable_set("@#{name}", arg)} # This is the setter
end
end
Cele mai multe dintre raspunsurile de mai sus folosesc cod. Această explicație încearcă să răspundă fără a utiliza orice, printr-o analogie/poveste:
În afara părți nu pot accesa interne secretele CIA
Daca're în afara CIA puteți accesa numai informațiile care trebuie puse la dispoziția publicului. Sau de a folosi CIA limbajul puteți accesa numai informațiile care sunt "șterse".
Informațiile pe care CIA vrea să facă disponibile publicului larg în afara CIA sunt numite: atribute.
Sensul de citire și scriere atribute:
În caz de CIA, cele mai multe atribute sunt "citi doar". Acest lucru înseamnă că, dacă sunteți o petrecere externe pentru CIA, puteți întreba: "care este director al CIA?" și veți primi un răspuns direct. Dar ce te nu cu "citi doar" atribute este de a face schimbări schimbări în CIA. de exemplu, nu puteți efectua un apel telefonic și brusc decidă pe care doriți Kim Kardashian a fi Director, sau pe care doriți Paris Hilton a fi Comandant suprem.
Dacă atributele ți-a dat "scrie" de acces, atunci ai putea face modificări, dacă vrei, chiar dacă ești afară. În caz contrar, singurul lucru care le puteți face este de a citi.
Cu alte cuvinte evaluatorilor permite să facă anchete, sau de a face modificări, pentru organizațiile care, altfel, nu lasa oameni externe, în funcție de faptul dacă evaluatorilor sunt citească sau să scrie evaluatorilor.
Obiecte în interiorul unei clase pot accesa cu ușurință fiecare alte
Exact același lucru cu clase și capacitatea de a accesa variabile, proprietăți și metode în cadrul acestora. HTH! Orice întrebări, vă rugăm să cereți și sper să pot clarifica.
Dacă sunteți familiarizat cu conceptul OOP, trebuie să Vă familiarizați cu getter și setter metodă. attr_accessor face același lucru în Ruby.
Getter și Setter în Mod General
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"
Metoda Setter
def name=(val)
@name = val
end
Metoda Getter
def name
@name
end
Getter și Setter metodă în Ruby
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
Am confruntat această problemă precum și a scris-o oarecum de lungă durată răspunsul la această întrebare. Sunt niște răspunsuri pe asta deja, dar oricine caută pentru mai multe clarificări, sper ca raspunsul meu poate ajuta
Inițializa Metoda
Inițializare vă permite să setați datele de la o instanță a unui obiect asupra creării de exemplu, mai degrabă decât a fi nevoie să setați-le pe o linie separată în codul de fiecare dată când creați o nouă instanță a clasei.
class Person
def initialize(name)
@name = name
end
def greeting
"Hello #{@name}"
end
end
person = Person.new("Denis")
puts person.greeting
În codul de mai sus stabilim numele de "Denis", folosind metoda initialize prin trecerea Dennis prin parametrul în Inițializa. Dacă ne-am dorit pentru a seta numele, fără a inițializa metodă ne-ar putea face astfel:
class Person
attr_accessor :name
# def initialize(name)
# @name = name
# end
def greeting
"Hello #{name}"
end
end
person = Person.new
person.name = "Dennis"
puts person.greeting
În codul de mai sus, ne-am stabilit numele de asteptare pe attr_accessor setter metoda folosind persoană.numele, mai degrabă decât de stabilirea la valori de inițializare a obiectului.
Ambele "metode" de a face acest lucru, dar inițializa ne salvează timp și de linii de cod.
Acesta este singurul loc de muncă de a inițializa. Nu poti suna pe inițializa ca o metodă. Pentru a obține de fapt, valorile de un exemplu de obiect, aveți nevoie pentru a utiliza getters și setteri (attr_reader (ia), attr_writer(set), și attr_accessor(ambele)). A se vedea mai jos pentru mai multe detalii cu privire la aceste.
Getters, Setteri (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: întregul scop de un getter este de a reveni la valoarea de o anumită variabilă de exemplu. Vizitați mostre de cod de mai jos pentru o defalcare pe asta.
class Item
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
def item_name
@item_name
end
def quantity
@quantity
end
end
example = Item.new("TV",2)
puts example.item_name
puts example.quantity
În codul de mai sus vă sunt de asteptare metodele "item_name" și "cantitate" pe exemplu de Articol "exemplu". A "pune de exemplu.item_name" și "exemplu.cantitatea" se va întoarce (sau "a lua") valoarea pentru parametrii care au trecut în "exemplu" și a le afișa pe ecran.
Din fericire, în Ruby nu este inerentă de metodă care ne permite să scrie acest cod mai succint; la attr_reader metodă. Vezi codul de mai jos;
class Item
attr_reader :item_name, :quantity
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
end
item = Item.new("TV",2)
puts item.item_name
puts item.quantity
Această sintaxă funcționează exact în același mod, numai că ne salvează de șase linii de cod. Imaginați-vă dacă ați avut mai mult de 5 de stat pot fi atribuite la clasa de Articol? Codul ar ajunge mult mai repede.
Setteri, attr_writer: Ce mi-a trecut până la prima cu metode setter este că, în ochii mei se părea că pentru a efectua un identice de funcție a inițializa metodă. Mai jos voi explica diferența bazează pe înțelegerea mea;
După cum a afirmat și mai înainte, a inițializa metodă vă permite să setați valori pentru o instanță a unui obiect asupra obiectului creației.
Dar ce se întâmplă dacă ai vrut pentru a seta valorile mai târziu, după ce instanță a fost creat, sau de a le schimba după ce au fost inițializate? Acesta ar fi un scenariu în cazul în care ați folosi o metoda setter. CARE ESTE DIFERENȚA. Nu trebuie să "stabilească" o stare deosebită când utilizați attr_writer metoda inițial.
Codul de mai jos este un exemplu de utilizare a unui setter metoda de a declara valoarea item_name pentru acest exemplu de Element clasa. Observați că vom continua să utilizați metoda getter attr_reader astfel încât să putem obține valorile și să le imprimați pe ecran, doar în cazul în care doriți să testați codul pe cont propriu.
class Item
attr_reader :item_name
def item_name=(str)
@item_name = (str)
end
end
Codul de mai jos este un exemplu de utilizare a attr_writer să o dată din nou a scurta codul nostru și de a salva timp.
class Item
attr_reader :item_name
attr_writer :item_name
end
item = Item.new
puts item.item_name = "TV"
Codul de mai jos este o reiterare a inițializa exemplul de mai sus de care ne folosim pentru a inițializa set de obiecte cu valoare de item_name la creație.
class Item
attr_reader :item_name
def initialize(item_name)
@item_name = item_name
end
end
item = Item.new("TV")
puts item.item_name
attr_accessor: Îndeplinește funcțiile de ambele attr_reader și attr_writer, economisind încă o linie de cod.
Cred că o parte din ceea ce confundă noi Rubyists/programatori (ca mine) este:
"de Ce't-am spus în instanță că are un anumit atribut (de exemplu, numele) și dă-care atribuie o valoare dintr-o lovitură?"
Un pic mai generalizat, dar acest lucru este cum se face clic pentru mine:
Având în vedere:
class Person
end
Am't definite Persoană ca pe ceva care poate avea un nume sau orice alte atribute pentru care contează.
Deci, dacă avem atunci:
baby = Person.new
...și încerca să le dea un nume...
baby.name = "Ruth"
Avem o **** eroare pentru că, în Rubyland, o Persoană din clasa de obiect nu este ceva care este asociat cu sau capabil de a fi un "nume" ... încă!
DAR putem folosi oricare dintre metodele indicate (a se vedea răspunsurile anterioare) ca un mod de a spune, "Un exemplu de o Persoană de clasă ("copil") poate acum au un atribut numit 'numele', prin urmare, nu numai că avem un sintactice mod de obținerea și setarea numele asta, dar e logic să facă acest lucru."
Din nou, lovind această întrebare de la un ușor diferită și mai generale unghi, dar sper că acest lucru ajută la următoarea instanță a clasei Persoana care găsește drumul lor spre acest thread.
Pur și simplu pune-l va defini un setter și getter pentru clasa.
Rețineți că
attr_reader :v is equivalant to
def v
@v
end
attr_writer :v is equivalant to
def v=(value)
@v=value
end
Deci
attr_accessor :v which means
attr_reader :v; attr_writer :v
sunt equivalant pentru a defini un setter și getter pentru clasa.
Un alt mod de a înțelege este să dau seama ce cod de eroare se elimină prin care au attr_accessor
.
Exemplu:
class BankAccount
def initialize( account_owner )
@owner = account_owner
@balance = 0
end
def deposit( amount )
@balance = @balance + amount
end
def withdraw( amount )
@balance = @balance - amount
end
end
Sunt disponibile următoarele metode:
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
Următoarele metode aruncă eroare:
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
"proprietar" și "echilibru" nu sunt, din punct de vedere tehnic, o metodă, dar un atribut. Clasa BankAccount nu au def proprietar " și " def echilibru
. Dacă nu, atunci puteți folosi cele două comenzi de mai jos. Dar aceste două metode sunt't acolo. Cu toate acestea, puteți acces atribute ca daca'd acces o metodă prin attr_accessor
!! Prin urmare, cuvântul attr_accessor
. Atribut. Accesor. Se accesează atribute ca ai acces la o metodă.
Adăugarea attr_accessor :echilibru, :proprietar
vă permite să scrie și să citească "echilibru" și "proprietar" "metoda". Acum puteți folosi ultimele 2 metode.
$ bankie.balance
$ bankie.owner
Definește un atribut numit pentru acest modul, în cazul în care numele este un simbol.id2name, creând un exemplu de variabilă (@nume) și un acces corespunzător metodă să-l citească. Creează, de asemenea, o metoda numita name= pentru a seta atributul.
module Mod
attr_accessor(:one, :two)
end
Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
Pentru a rezuma un atribut accesor aka attr_accessor vă oferă două metode gratuite.
Ca și în Java se numeste getters și setteri.
Multe răspunsuri au prezentat exemple de bune, așa că am'm doar de gând să fie scurtă.
#the_attribute
și
#the_attribute=
În vechiul ruby docs un hash tag-ul # înseamnă o metodă. Aceasta ar putea include, de asemenea, un nume de clasă prefix... MyClass#my_method
Sunt nou ruby și a avut de a face doar cu înțelegerea următoarele ciudatenie. S-ar putea ajuta pe cineva in viitor. În cele din urmă este cum a fost menționat mai sus, în cazul în care 2 funcții (def myvar, def myvar=) amândoi implicit pentru accesarea @myvar, dar aceste metode pot fi înlocuite de către autoritățile locale declarații.
class Foo
attr_accessor 'myvar'
def initialize
@myvar = "A"
myvar = "B"
puts @myvar # A
puts myvar # B - myvar declared above overrides myvar method
end
def test
puts @myvar # A
puts myvar # A - coming from myvar accessor
myvar = "C" # local myvar overrides accessor
puts @myvar # A
puts myvar # C
send "myvar=", "E" # not running "myvar =", but instead calls setter for @myvar
puts @myvar # E
puts myvar # C
end
end
Atributele sunt clasa de componente care pot fi accesate din afara obiectului. Acestea sunt cunoscute ca proprietăți în multe alte limbaje de programare. Valorile lor sunt accesibile prin utilizarea "notația punct", ca în nume_obiect.nume_atribut. Spre deosebire de Python și alte câteva limbi, Ruby nu permite variabile de instanta pentru a fi accesate direct din exteriorul obiectului.
class Car
def initialize
@wheels = 4 # This is an instance variable
end
end
c = Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
În exemplul de mai sus, c este o instanță (obiect) al clasei Auto. Am încercat, fără succes, să citiți valoarea de roți de exemplu variabile din afara obiectului. Ce s-a întâmplat este că Ruby a încercat pentru a apela o metodă numită roți în cadrul c obiect, dar nici o astfel de metodă a fost definit. Pe scurt, nume_obiect.nume_atribut încearcă pentru a apela o metodă numită nume_atribut în cadrul obiectului. Pentru a accesa valoarea roți variabilă din exterior, trebuie să pună în aplicare o metodă de instanță cu acest nume, care va returna valoarea acestei variabile atunci când este solicitat. Ca's a numit-o metoda accesor. În general programare context, modul obișnuit de a accesa o variabilă instanță din afara obiect este de a pune în aplicare metode accesor, de asemenea, cunoscut sub numele de metode getter si setter. Un getter permite valoarea unei variabile definite într-o clasă să fie citit de exterior și un setter permite să fie scrise din exterior.
În următorul exemplu, am adăugat metode getter si setter la clasa Auto pentru a accesa roți variabile din afara obiectului. Acest lucru nu este "mod de Rubin" de definire a getters și setteri; ea servește doar pentru a ilustra ce metode getter si setter face.
class Car
def wheels # getter method
@wheels
end
def wheels=(val) # setter method
@wheels = val
end
end
f = Car.new
f.wheels = 4 # The setter method was invoked
f.wheels # The getter method was invoked
# Output: => 4
Exemplul de mai sus funcționează și similare de cod este frecvent utilizat pentru a crea metode getter si setter în alte limbi. Cu toate acestea, Ruby oferă un mod simplu de a face acest lucru: de trei built-in metode numit attr_reader, attr_writer și attr_acessor. La attr_reader metodă face o variabilă de exemplu poate fi citit din exterior, attr_writer face inscriptibil, și attr_acessor face ușor de citit și de inscripționare.
Exemplul de mai sus poate fi rescris astfel.
class Car
attr_accessor :wheels
end
f = Car.new
f.wheels = 4
f.wheels # Output: => 4
În exemplul de mai sus, roțile atribut va fi ușor de citit și scriere din afara obiectului. Dacă în loc de attr_accessor, am folosit attr_reader, ar fi read-only. Dacă am folosit attr_writer, ar fi doar pentru scriere. Cele trei metode nu sunt getters și setteri în ei înșiși, ci, atunci când este solicitat, vor crea metode getter si setter pentru noi. Acestea sunt metode care în mod dinamic (programatic) de a genera alte metode; ca's a numit metaprogram.
Prima (mai), de exemplu, care nu angajează Ruby's built-in metode, ar trebui să fie utilizat numai atunci când un cod suplimentar este necesar în metode getter si setter. De exemplu, un setter metoda ar putea avea nevoie pentru a valida datele sau de a face un calcul înainte de a atribui o valoare pentru o variabilă de exemplu.
Este posibil pentru a accesa (a se citi și scrie) variabile de instanta din afara obiectului, cu ajutorul instance_variable_get și instance_variable_set built-in metode. Cu toate acestea, acest lucru este rareori justificată și, de obicei, o idee rea, ca ocolind încapsulare tinde să facă tot felul de haos.
Hmmm. O mulțime de răspunsuri bune. Aici este meu de câțiva cenți pe ea.
attr_accessor
este o metodă simplă care ne ajută în curățarea(USCAT-ing) până la repetarea getter și setter
metode.
Așa că ne putem concentra mai mult pe scris de logica de afaceri și nu vă faceți griji despre setteri și ambiție.
Principala funcționalitate a attr_accessor peste celelalte este capacitatea de a accesa date din alte fișiere. Așa că, de obicei, ar fi attr_reader sau attr_writer dar vestea bună este că Ruby vă permite să combinați aceste două împreună cu attr_accessor. Eu cred ca mea de a merge metoda pentru că este mult mai bine rotunjite sau versatil. De asemenea, peep în vedere faptul că în Șine, acesta este eliminat, pentru că o face pentru tine în back-end. Deci, cu alte cuvinte: esti mai bine folosind attr_acessor peste alte două pentru că tu nu't trebuie să vă faceți griji despre a fi specifice, accesor acoperă totul. Știu că acest lucru este mai mult de o explicație generală, dar m-a ajutat ca un incepator.
Sper că acest lucru a ajutat!