Funktioniert attr_accessor in Git genauso? Ich stelle fest, dass einige Tutorials nicht genug erklären und andere Vorkenntnisse voraussetzen.
Angelfirenze
10
@ Angelfirenze, githat nichts damit zu tun attr_accessor. Git ist eine Versionskontrollsoftware, während attr_accessores sich bei Ruby um eine Methode handelt .
Usbekjon
Antworten:
2360
Angenommen, Sie haben eine Klasse Person.
classPersonend
person =Person.new
person.name # => no method error
Offensichtlich haben wir nie eine Methode definiert name. Lass uns das tun.
classPersondef name@name# simply returning an instance variable @nameendend
person =Person.new
person.name # => nil
person.name ="Dennis"# => no method error
Aha, wir können den Namen lesen, aber das bedeutet nicht, dass wir den Namen zuweisen können. Das sind zwei verschiedene Methoden. Ersteres heißt Leser und letzteres Schriftsteller . Wir haben den Autor noch nicht erstellt, also machen wir das.
Genial. Jetzt können wir Instanzvariablen @namemit Lese- und Schreibmethoden schreiben und lesen . Außer, dass dies so häufig gemacht wird, warum sollte man jedes Mal Zeit damit verschwenden, diese Methoden zu schreiben? Wir können es einfacher machen.
Funktioniert genauso! Und raten Sie mal: Die Instanzvariable @namein unserem Personenobjekt wird genau wie bei der manuellen Ausführung festgelegt, sodass Sie sie in anderen Methoden verwenden können.
Das ist es. Um zu verstehen , wie attr_reader, attr_writerund attr_accessorMethoden tatsächlich Methoden für Sie generieren, lesen Sie andere Antworten, Bücher, Rubin docs.
@akunin - danke für diese klare Antwort. Was mir fehlt, ist, warum die Ruby-Syntax einen Doppelpunkt ':' für die Instanzvariablen in der attr_ * -Anweisung vorschlägt? Es scheint einfacher zu sein, dieselbe '@' - Syntax zu verwenden, die an anderer Stelle in der Klasse verwendet wird, um auf die Variable zu verweisen.
Will
207
@WilliamSmith Um Ihre Frage zu beantworten, müssen Sie verstehen, dass attr_accessores sich um eine Methode handelt, die für die aktuelle Klasse aufgerufen wird und die :nameSie an diese Methode übergeben. Es ist keine spezielle Syntax, sondern ein einfacher Methodenaufruf. Wenn Sie ihm eine @nameVariable geben würden, wäre dies nicht sinnvoll, da @name enthalten würde nil. Es wäre also wie beim Schreiben attr_accessor nil. Sie übergeben ihm keine Variable, die erstellt werden muss, sondern den Namen, unter dem die Variable aufgerufen werden soll.
Max Chernyak
23
@akunin - Das macht total Sinn. Ich habe gerade heute erfahren, dass Ruby tatsächlich "läuft", während es eine Datei analysiert, und dass jede Anweisung und jeder Ausdruck tatsächlich ein Methodenaufruf für ein Objekt ist. Einschließlich attr_accessor. Sehr hilfreich.
Will
52
benutzte Rails für 3 Jahre, wusste das noch nie. Schade
Sean Xiao
5
@Buminda ja, aber Methode nameund Variable @namesind nicht dasselbe. Verwirre sie nicht. Sie haben eine Instanzvariable @namein Ihrer Klasse und definieren attr_reader :namediese, um sie von außen lesen zu können. Ohne attr_readergibt es keine einfache Möglichkeit, @nameaußerhalb Ihrer Klasse zuzugreifen .
Max Chernyak
127
attr_accessor ist nur eine Methode . (Der Link sollte mehr Einblick in die Funktionsweise geben. Sehen Sie sich die generierten Methodenpaare an, und ein Tutorial sollte Ihnen zeigen, wie Sie ihn verwenden.)
Der Trick ist, dass classes sich nicht um eine Definition in Ruby handelt (es ist "nur eine Definition" in Sprachen wie C ++ und Java), sondern um einen Ausdruck, der ausgewertet wird . Während dieser Auswertung wird die attr_accessorMethode aufgerufen, die wiederum die aktuelle Klasse ändert. Denken Sie an den impliziten Empfänger : self.attr_accessor, wo selfsich an dieser Stelle das "offene" Klassenobjekt befindet.
Das Bedürfnis nach attr_accessorund nach Freunden ist:
Ruby erlaubt wie Smalltalk nicht, auf Instanzvariablen außerhalb von Methode 1 für dieses Objekt zuzugreifen. Das heißt, auf Instanzvariablen kann nicht in der x.yForm zugegriffen werden , wie dies beispielsweise in Java oder sogar Python üblich ist. In Ruby ywird immer eine Nachricht zum Senden (oder "Methode zum Aufrufen") verwendet. Auf diese Weise attr_*erstellen die Methoden Wrapper, die den Instanzzugriff @variableüber dynamisch erstellte Methoden übertragen.
Boilerplate saugt
Ich hoffe, dies verdeutlicht einige der kleinen Details. Viel Spaß beim Codieren.
1 Dies ist nicht unbedingt der Fall und es gibt einige "Techniken" , aber es gibt keine Syntaxunterstützung für den Zugriff auf "öffentliche Instanzvariablen".
Wenn Sie sagen, attr_accessor sei "nur eine Methode", verstehe ich das. Aber was ist die Syntax verwendet , um Aufruf aufgerufen diese Methode? Ich habe Probleme, den Abschnitt in der Ruby-Dokumentation zu finden, der sich mit Syntax wie some_method: name => "was auch immer" ,: notherName ,: etc
BT
68
attr_accessorist (wie @pst sagte) nur eine Methode. Es werden mehr Methoden für Sie erstellt.
Also dieser Code hier:
classFoo
attr_accessor :bar
end
entspricht diesem Code:
classFoodef bar
@barenddef bar=( new_value )@bar= new_value
endend
Sie können diese Art von Methode selbst in Ruby schreiben:
classModuledef 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
endendendclassFoo
var :bar
end
f =Foo.new
p f.bar #=> nil
f.bar =42
p f.bar #=> 42
Dies ist ein großartiges Beispiel dafür, wo Metaprogrammierung selbst in Szenarien für Anfänger verwendet wird. Sehr schön.
John Simon
2
Ich habe nach einer Implementierungsskizze gesucht attr_accessorund hier endlich gefunden! Es hat zwar mein Problem gelöst, aber ich bin gespannt, wo (Buch / offizielles Dokument) ich ein solches Implementierungsbeispiel finden kann.
Wasif Hossain
40
attr_accessor ist sehr einfach:
attr_accessor :foo
ist eine Abkürzung für:
def foo=(val)@foo= val
enddef foo
@fooend
Es ist nichts weiter als ein Getter / Setter für ein Objekt
Ihre Antwort ist in Ordnung. 'Shortcut' bedeutet laut meinem Wörterbuch "eine kürzere alternative Route", nicht "Syntaxzucker" oder "vom Interpreter interpretiertes Makro".
Bowsersenior
25
Grundsätzlich fälschen sie öffentlich zugängliche Datenattribute, die Ruby nicht hat.
Obwohl dieser Kommentar nicht ganz nützlich ist, ist er wahr. Hebt die Tatsache hervor, dass öffentliche Datenattribute außerhalb der "get" -Methoden in Ruby nicht vorhanden sind. Dies ist eine sehr nützliche Information für jemanden, der versucht, die Sprache zu lernen.
Eric Dand
3
Dies sollte wirklich nicht herabgestuft werden. Als Nicht-Ruby-Typ, der versucht, dieses Zeug herauszufinden, ist diese Antwort sehr hilfreich!
Brad
1
Einverstanden, scheint dem Namen von C # sehr ähnlich zu sein {get; set;}
David Miler
17
Es ist nur eine Methode, die Getter- und Setter-Methoden für Instanzvariablen definiert. Eine beispielhafte Implementierung wäre:
defself.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 setterendend
Der Umgang mit mehreren Attributen auf diese Weise ist großartig!
Wasif Hossain
Dies war ein wirklich hilfreicher Code-Ausschnitt, um eine andere Frage zu lösen, die ich im Zusammenhang mit der Metaprogrammierung hatte.
Alexventuraio
15
Einfache Erklärung ohne Code
Die meisten der oben genannten Antworten verwenden Code. Diese Erklärung versucht, sie ohne Verwendung einer zu beantworten, und zwar über eine Analogie / Geschichte:
Externe Parteien können nicht auf interne CIA-Geheimnisse zugreifen
Stellen wir uns einen wirklich geheimen Ort vor: die CIA. Niemand weiß, was in der CIA passiert, außer den Leuten innerhalb der CIA. Mit anderen Worten, externe Personen können nicht auf Informationen in der CIA zugreifen. Aber weil es nicht gut ist, eine Organisation zu haben, die völlig geheim ist, werden bestimmte Informationen der Außenwelt zur Verfügung gestellt - nur Dinge, über die die CIA natürlich alle wissen lassen möchte: zB der Direktor der CIA, wie umweltfreundlich diese Abteilung verglichen wird an alle anderen Regierungsabteilungen usw. Weitere Informationen: zB wer sind seine verdeckten Agenten im Irak oder in Afghanistan - diese Art von Dingen wird wahrscheinlich für die nächsten 150 Jahre ein Geheimnis bleiben.
Wenn Sie sich außerhalb der CIA befinden, können Sie nur auf die Informationen zugreifen, die der Öffentlichkeit zur Verfügung gestellt wurden. Um die CIA-Sprache zu verwenden, können Sie nur auf Informationen zugreifen, die "gelöscht" sind.
Die Informationen, die die CIA der Öffentlichkeit außerhalb der CIA zur Verfügung stellen möchte, werden als Attribute bezeichnet.
Die Bedeutung von Lese- und Schreibattributen:
Im Fall der CIA sind die meisten Attribute "schreibgeschützt". Das heißt, wenn Sie eine Partei außerhalb der CIA sind, können Sie fragen: "Wer ist der Direktor der CIA?" und Sie erhalten eine klare Antwort. Mit "schreibgeschützten" Attributen können Sie jedoch keine Änderungen an der CIA vornehmen. Sie können beispielsweise nicht telefonieren und plötzlich entscheiden , dass Kim Kardashian der Direktor sein soll oder dass Paris Hilton der Oberbefehlshaber sein soll.
Wenn Sie durch die Attribute Schreibzugriff erhalten, können Sie Änderungen vornehmen, wenn Sie möchten, auch wenn Sie sich außerhalb befinden. Ansonsten können Sie nur lesen.
Mit anderen Worten, mit Accessoren können Sie Anfragen an Organisationen stellen oder Änderungen vornehmen, die ansonsten keine externen Personen zulassen, je nachdem, ob es sich bei den Accessoren um Lese- oder Schreib-Accessoren handelt.
Objekte innerhalb einer Klasse können leicht aufeinander zugreifen
Wenn Sie sich jedoch bereits in der CIA befanden , können Sie Ihren CIA-Mitarbeiter in Kabul problemlos anrufen, da diese Informationen leicht zugänglich sind , sofern Sie sich bereits in der CIA befinden. Wenn Sie sich jedoch außerhalb der CIA befinden, erhalten Sie einfach keinen Zugriff: Sie können nicht wissen, wer sie sind (Lesezugriff), und Sie können ihre Mission nicht ändern (Schreibzugriff).
Genau das Gleiche gilt für Klassen und Ihre Fähigkeit, auf Variablen, Eigenschaften und Methoden in ihnen zuzugreifen. HTH! Fragen, bitte stellen und ich hoffe, ich kann klären.
Ihre Erklärung macht Sinn! +1 Entschuldigung, sind Sie sicher, dass der Ausdruck "Informationen, die von der CIA gelöscht werden, richtig ist?
Kouty
In der CIA gibt es verschiedene "Freigabestufen": z. B. streng geheim (niemand außer dem Prez) oder öffentliches Vertrauen (jeder kann diese Informationen lesen). Die CIA liefert tatsächlich viele sehr coole Fakten!
BKSpurgeon
Sie verdienen die Gegenstimme nur für die Beispiele von Kardashian, Paris Hilton :) Ich dachte, es wäre schon schlimm genug mit Trump als Präsident, stellen Sie sich die beiden Verantwortlichen vor, omg!
rmcsharry
Ja! Das ist was wir brauchen, StackOverflow ohne Code! :-)
Marvin
13
Wenn Sie mit dem OOP-Konzept vertraut sind, müssen Sie mit der Getter- und Setter-Methode vertraut sein. attr_accessor macht dasselbe in Ruby.
Getter und Setter im Allgemeinen
classPersondef name
@nameenddef name=(str)@name= str
endend
person =Person.new
person.name ='Eshaan'
person.name # => "Eshaan"
Setter-Methode
def name=(val)@name= val
end
Getter-Methode
def name
@nameend
Getter- und Setter-Methode in Ruby
classPerson
attr_accessor :name
end
person =Person.new
person.name ="Eshaan"
person.name # => "Eshaan"
perfekte Erklärung! Es ist ein sehr praktisches Verhalten und kann zu leicht überschrieben werden.
Rubyrider
12
Ich habe mich auch diesem Problem gestellt und eine etwas längere Antwort auf diese Frage geschrieben. Es gibt bereits einige gute Antworten darauf, aber jeder, der mehr Klarheit sucht, hoffe, dass meine Antwort helfen kann
Methode initialisieren
Mit "Initialisieren" können Sie beim Erstellen der Instanz Daten für eine Instanz eines Objekts festlegen, anstatt sie jedes Mal, wenn Sie eine neue Instanz der Klasse erstellen, in einer separaten Zeile in Ihrem Code festlegen zu müssen.
classPersondef initialize(name)@name= name
enddef greeting
"Hello #{@name}"endend
person =Person.new("Denis")
puts person.greeting
Im obigen Code setzen wir den Namen "Denis" mit der Initialisierungsmethode, indem wir Dennis durch den Parameter in Initialize übergeben. Wenn wir den Namen ohne die Initialisierungsmethode festlegen möchten, können wir dies folgendermaßen tun:
Im obigen Code legen wir den Namen fest, indem wir die Setter-Methode attr_accessor mit person.name aufrufen, anstatt die Werte bei der Initialisierung des Objekts festzulegen.
Beide „Methoden“, um diese Arbeit auszuführen, aber das Initialisieren spart uns Zeit und Codezeilen.
Dies ist die einzige Aufgabe zum Initialisieren. Sie können die Initialisierung nicht als Methode aufrufen. Um die Werte eines Instanzobjekts tatsächlich abzurufen, müssen Sie Getter und Setter (attr_reader (get), attr_writer (set) und attr_accessor (beide)) verwenden. Weitere Einzelheiten hierzu finden Sie weiter unten.
Getters, attr_reader: Der gesamte Zweck eines Getters besteht darin, den Wert einer bestimmten Instanzvariablen zurückzugeben. Besuchen Sie den folgenden Beispielcode, um eine Aufschlüsselung zu diesem Thema zu erhalten.
Im obigen Code rufen Sie die Methoden "item_name" und "Quantity" für die Instanz von Item "example" auf. Die "Puts example.item_name" und "example.quantity" geben den Wert für die Parameter zurück (oder "get"), die an das "example" übergeben wurden, und zeigen sie auf dem Bildschirm an.
Glücklicherweise gibt es in Ruby eine inhärente Methode, mit der wir diesen Code prägnanter schreiben können. die attr_reader-Methode. Siehe den Code unten;
Diese Syntax funktioniert genauso, nur dass wir sechs Codezeilen sparen. Stellen Sie sich vor, Sie hätten 5 weitere Status, die der Item-Klasse zugeordnet werden können? Der Code würde schnell lang werden.
Setter, attr_writer: Was mich anfangs mit Setter-Methoden beschäftigt hat, ist, dass es in meinen Augen eine identische Funktion wie die Initialisierungsmethode zu haben schien. Im Folgenden erkläre ich den Unterschied anhand meines Verständnisses.
Wie bereits erwähnt, können Sie mit der Initialisierungsmethode die Werte für eine Instanz eines Objekts bei der Objekterstellung festlegen.
Was aber, wenn Sie die Werte später nach dem Erstellen der Instanz festlegen oder nach der Initialisierung ändern möchten? Dies wäre ein Szenario, in dem Sie eine Setter-Methode verwenden würden. DAS IST DER UNTERSCHIED. Sie müssen keinen bestimmten Status festlegen, wenn Sie anfänglich die attr_writer-Methode verwenden.
Der folgende Code ist ein Beispiel für die Verwendung einer Setter-Methode, um den Wert item_name für diese Instanz der Item-Klasse zu deklarieren. Beachten Sie, dass wir weiterhin die Getter-Methode attr_reader verwenden, damit wir die Werte abrufen und auf dem Bildschirm drucken können, nur für den Fall, dass Sie den Code selbst testen möchten.
Der folgende Code ist eine Wiederholung des obigen Initialisierungsbeispiels, bei dem wir initialize verwenden, um den Objektwert von item_name bei der Erstellung festzulegen.
Ich denke, ein Teil dessen, was neue Rubyisten / Programmierer (wie mich) verwirrt, ist:
"Warum kann ich der Instanz nicht einfach sagen, dass sie ein bestimmtes Attribut (z. B. einen Namen) hat, und diesem Attribut auf einen Schlag einen Wert geben?"
Ein bisschen allgemeiner, aber so hat es für mich geklickt:
Gegeben:
classPersonend
Wir haben Person nicht als etwas definiert , das einen Namen oder andere Attribute für diese Angelegenheit haben kann.
Also wenn wir dann:
baby =Person.new
... und versuche ihnen einen Namen zu geben ...
baby.name ="Ruth"
Wir erhalten eine Fehlermeldung, weil in Rubyland eine Person-Objektklasse nicht mit einem "Namen" assoziiert ist oder einen solchen haben kann ... noch nicht!
ABER wir können jede der angegebenen Methoden verwenden (siehe vorherige Antworten), um zu sagen: "Eine Instanz einer Person-Klasse ( baby) kann jetzt ein Attribut namens 'name' haben, daher haben wir nicht nur eine syntaktische Methode, um und zu erhalten diesen Namen setzen, aber es ist sinnvoll für uns, dies zu tun. "
Wiederum diese Frage aus einem etwas anderen und allgemeineren Blickwinkel zu beantworten, aber ich hoffe, dies hilft der nächsten Instanz der Klasse Person, die ihren Weg zu diesem Thread findet.
ownerund balancesind technisch gesehen keine Methode , sondern ein Attribut. Bankaccount - Klasse nicht haben def ownerund def balance. Wenn dies der Fall ist, können Sie die beiden folgenden Befehle verwenden. Aber diese beiden Methoden sind nicht da. Sie können jedoch auf Attribute zugreifen , als würden Sie über !! auf eine Methode zugreifen. Daher das Wort . Attribut. Accessor. Es greift auf Attribute zu, als würden Sie auf eine Methode zugreifen.attr_accessorattr_accessor
Durch Hinzufügen attr_accessor :balance, :ownerkönnen Sie lesen und schreiben balanceund owner"Methode". Jetzt können Sie die letzten beiden Methoden verwenden.
Definiert ein benanntes Attribut für dieses Modul, wobei der Name symbol.id2name lautet, und erstellt eine Instanzvariable (@name) und eine entsprechende Zugriffsmethode zum Lesen. Erstellt auch eine Methode namens name =, um das Attribut festzulegen.
Ich bin neu in Ruby und musste mich nur mit dem Verständnis der folgenden Verrücktheit befassen. Könnte in Zukunft jemand anderem helfen. Am Ende ist es wie oben erwähnt, wo 2 Funktionen (def myvar, def myvar =) implizit für den Zugriff auf @myvar abgerufen werden, aber diese Methoden können durch lokale Deklarationen überschrieben werden.
classFoo
attr_accessor 'myvar'def initialize
@myvar="A"
myvar ="B"
puts @myvar# A
puts myvar # B - myvar declared above overrides myvar methodenddef 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 # Cendend
Attribute sind Klassenkomponenten, auf die von außerhalb des Objekts zugegriffen werden kann. Sie sind in vielen anderen Programmiersprachen als Eigenschaften bekannt. Auf ihre Werte kann mithilfe der "Punktnotation" wie in object_name.attribute_name zugegriffen werden. Im Gegensatz zu Python und einigen anderen Sprachen erlaubt Ruby keinen direkten Zugriff auf Instanzvariablen von außerhalb des Objekts.
classCardef initialize
@wheels=4# This is an instance variableendend
c =Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
Im obigen Beispiel ist c eine Instanz (ein Objekt) der Car-Klasse. Wir haben erfolglos versucht, den Wert der Instanzvariablen der Räder von außerhalb des Objekts zu lesen. Was passiert ist, ist, dass Ruby versucht hat, eine Methode namens ribs innerhalb des c-Objekts aufzurufen, aber keine solche Methode wurde definiert. Kurz gesagt, object_name.attribute_name versucht, eine Methode namens attribute_name innerhalb des Objekts aufzurufen. Um von außen auf den Wert der Radvariablen zuzugreifen, müssen wir eine Instanzmethode mit diesem Namen implementieren, die beim Aufruf den Wert dieser Variablen zurückgibt. Das nennt man eine Accessor-Methode. Im allgemeinen Programmierkontext besteht die übliche Möglichkeit, von außerhalb des Objekts auf eine Instanzvariable zuzugreifen, darin, Zugriffsmethoden zu implementieren, die auch als Getter- und Setter-Methoden bezeichnet werden.
Im folgenden Beispiel haben wir der Car-Klasse Getter- und Setter-Methoden hinzugefügt, um von außerhalb des Objekts auf die Rädervariable zuzugreifen. Dies ist nicht die "Ruby-Methode", um Getter und Setter zu definieren. Es dient nur zur Veranschaulichung der Funktionsweise von Getter- und Setter-Methoden.
classCardef wheels # getter method@wheelsenddef wheels=(val)# setter method@wheels= val
endend
f =Car.new
f.wheels =4# The setter method was invoked
f.wheels # The getter method was invoked# Output: => 4
Das obige Beispiel funktioniert und ähnlicher Code wird häufig verwendet, um Getter- und Setter-Methoden in anderen Sprachen zu erstellen. Ruby bietet jedoch eine einfachere Möglichkeit, dies zu tun: drei integrierte Methoden namens attr_reader, attr_writer und attr_acessor. Die attr_reader-Methode macht eine Instanzvariable von außen lesbar, attr_writer macht sie beschreibbar und attr_acessor macht sie lesbar und beschreibbar.
Das obige Beispiel kann so umgeschrieben werden.
classCar
attr_accessor :wheels
end
f =Car.new
f.wheels =4
f.wheels # Output: => 4
Im obigen Beispiel ist das Attribut "Räder" von außerhalb des Objekts lesbar und beschreibbar. Wenn wir anstelle von attr_accessor attr_reader verwenden würden, wäre dies schreibgeschützt. Wenn wir attr_writer verwenden würden, wäre es schreibgeschützt. Diese drei Methoden sind an sich keine Getter und Setter, aber wenn sie aufgerufen werden, erstellen sie Getter- und Setter-Methoden für uns. Dies sind Methoden, die dynamisch (programmgesteuert) andere Methoden generieren. Das nennt man Metaprogrammierung.
Das erste (längere) Beispiel, in dem Rubys integrierte Methoden nicht verwendet werden, sollte nur verwendet werden, wenn in den Getter- und Setter-Methoden zusätzlicher Code erforderlich ist. Beispielsweise muss eine Setter-Methode möglicherweise Daten validieren oder Berechnungen durchführen, bevor einer Instanzvariablen ein Wert zugewiesen wird.
Mit den integrierten Methoden instance_variable_get und instance_variable_set können Sie von außerhalb des Objekts auf Instanzvariablen zugreifen (diese lesen und schreiben). Dies ist jedoch selten zu rechtfertigen und in der Regel eine schlechte Idee, da die Umgehung der Kapselung dazu neigt, alle Arten von Chaos zu verursachen.
Die Hauptfunktionalität von attr_accessor gegenüber den anderen ist die Möglichkeit, auf Daten aus anderen Dateien zuzugreifen.
Normalerweise haben Sie attr_reader oder attr_writer, aber die gute Nachricht ist, dass Sie mit Ruby diese beiden mit attr_accessor kombinieren können. Ich betrachte es als meine To-Go-Methode, weil es runder oder vielseitiger ist. Denken Sie auch daran, dass dies in Rails beseitigt ist, da es im Back-End für Sie erledigt wird. Mit anderen Worten: Sie sind besser dran, attr_acessor gegenüber den beiden anderen zu verwenden, da Sie sich keine Sorgen machen müssen, dass Sie zu spezifisch sind. Der Accessor deckt alles ab. Ich weiß, dass dies eher eine allgemeine Erklärung ist, aber es hat mir als Anfänger geholfen.
git
hat nichts damit zu tunattr_accessor
. Git ist eine Versionskontrollsoftware, währendattr_accessor
es sich bei Ruby um eine Methode handelt .Antworten:
Angenommen, Sie haben eine Klasse
Person
.Offensichtlich haben wir nie eine Methode definiert
name
. Lass uns das tun.Aha, wir können den Namen lesen, aber das bedeutet nicht, dass wir den Namen zuweisen können. Das sind zwei verschiedene Methoden. Ersteres heißt Leser und letzteres Schriftsteller . Wir haben den Autor noch nicht erstellt, also machen wir das.
Genial. Jetzt können wir Instanzvariablen
@name
mit Lese- und Schreibmethoden schreiben und lesen . Außer, dass dies so häufig gemacht wird, warum sollte man jedes Mal Zeit damit verschwenden, diese Methoden zu schreiben? Wir können es einfacher machen.Auch dies kann sich wiederholen. Wenn Sie sowohl Leser als auch Schreiber möchten, verwenden Sie einfach Accessor!
Funktioniert genauso! Und raten Sie mal: Die Instanzvariable
@name
in unserem Personenobjekt wird genau wie bei der manuellen Ausführung festgelegt, sodass Sie sie in anderen Methoden verwenden können.Das ist es. Um zu verstehen , wie
attr_reader
,attr_writer
undattr_accessor
Methoden tatsächlich Methoden für Sie generieren, lesen Sie andere Antworten, Bücher, Rubin docs.quelle
attr_accessor
es sich um eine Methode handelt, die für die aktuelle Klasse aufgerufen wird und die:name
Sie an diese Methode übergeben. Es ist keine spezielle Syntax, sondern ein einfacher Methodenaufruf. Wenn Sie ihm eine@name
Variable geben würden, wäre dies nicht sinnvoll, da @name enthalten würdenil
. Es wäre also wie beim Schreibenattr_accessor nil
. Sie übergeben ihm keine Variable, die erstellt werden muss, sondern den Namen, unter dem die Variable aufgerufen werden soll.name
und Variable@name
sind nicht dasselbe. Verwirre sie nicht. Sie haben eine Instanzvariable@name
in Ihrer Klasse und definierenattr_reader :name
diese, um sie von außen lesen zu können. Ohneattr_reader
gibt es keine einfache Möglichkeit,@name
außerhalb Ihrer Klasse zuzugreifen .attr_accessor ist nur eine Methode . (Der Link sollte mehr Einblick in die Funktionsweise geben. Sehen Sie sich die generierten Methodenpaare an, und ein Tutorial sollte Ihnen zeigen, wie Sie ihn verwenden.)
Der Trick ist, dass
class
es sich nicht um eine Definition in Ruby handelt (es ist "nur eine Definition" in Sprachen wie C ++ und Java), sondern um einen Ausdruck, der ausgewertet wird . Während dieser Auswertung wird dieattr_accessor
Methode aufgerufen, die wiederum die aktuelle Klasse ändert. Denken Sie an den impliziten Empfänger :self.attr_accessor
, woself
sich an dieser Stelle das "offene" Klassenobjekt befindet.Das Bedürfnis nach
attr_accessor
und nach Freunden ist:Ruby erlaubt wie Smalltalk nicht, auf Instanzvariablen außerhalb von Methode 1 für dieses Objekt zuzugreifen. Das heißt, auf Instanzvariablen kann nicht in der
x.y
Form zugegriffen werden , wie dies beispielsweise in Java oder sogar Python üblich ist. In Rubyy
wird immer eine Nachricht zum Senden (oder "Methode zum Aufrufen") verwendet. Auf diese Weiseattr_*
erstellen die Methoden Wrapper, die den Instanzzugriff@variable
über dynamisch erstellte Methoden übertragen.Boilerplate saugt
Ich hoffe, dies verdeutlicht einige der kleinen Details. Viel Spaß beim Codieren.
1 Dies ist nicht unbedingt der Fall und es gibt einige "Techniken" , aber es gibt keine Syntaxunterstützung für den Zugriff auf "öffentliche Instanzvariablen".
quelle
attr_accessor
ist (wie @pst sagte) nur eine Methode. Es werden mehr Methoden für Sie erstellt.Also dieser Code hier:
entspricht diesem Code:
Sie können diese Art von Methode selbst in Ruby schreiben:
quelle
attr_accessor
und hier endlich gefunden! Es hat zwar mein Problem gelöst, aber ich bin gespannt, wo (Buch / offizielles Dokument) ich ein solches Implementierungsbeispiel finden kann.attr_accessor
ist sehr einfach:ist eine Abkürzung für:
Es ist nichts weiter als ein Getter / Setter für ein Objekt
quelle
Grundsätzlich fälschen sie öffentlich zugängliche Datenattribute, die Ruby nicht hat.
quelle
Es ist nur eine Methode, die Getter- und Setter-Methoden für Instanzvariablen definiert. Eine beispielhafte Implementierung wäre:
quelle
Einfache Erklärung ohne Code
Die meisten der oben genannten Antworten verwenden Code. Diese Erklärung versucht, sie ohne Verwendung einer zu beantworten, und zwar über eine Analogie / Geschichte:
Externe Parteien können nicht auf interne CIA-Geheimnisse zugreifen
Stellen wir uns einen wirklich geheimen Ort vor: die CIA. Niemand weiß, was in der CIA passiert, außer den Leuten innerhalb der CIA. Mit anderen Worten, externe Personen können nicht auf Informationen in der CIA zugreifen. Aber weil es nicht gut ist, eine Organisation zu haben, die völlig geheim ist, werden bestimmte Informationen der Außenwelt zur Verfügung gestellt - nur Dinge, über die die CIA natürlich alle wissen lassen möchte: zB der Direktor der CIA, wie umweltfreundlich diese Abteilung verglichen wird an alle anderen Regierungsabteilungen usw. Weitere Informationen: zB wer sind seine verdeckten Agenten im Irak oder in Afghanistan - diese Art von Dingen wird wahrscheinlich für die nächsten 150 Jahre ein Geheimnis bleiben.
Wenn Sie sich außerhalb der CIA befinden, können Sie nur auf die Informationen zugreifen, die der Öffentlichkeit zur Verfügung gestellt wurden. Um die CIA-Sprache zu verwenden, können Sie nur auf Informationen zugreifen, die "gelöscht" sind.
Die Informationen, die die CIA der Öffentlichkeit außerhalb der CIA zur Verfügung stellen möchte, werden als Attribute bezeichnet.
Die Bedeutung von Lese- und Schreibattributen:
Im Fall der CIA sind die meisten Attribute "schreibgeschützt". Das heißt, wenn Sie eine Partei außerhalb der CIA sind, können Sie fragen: "Wer ist der Direktor der CIA?" und Sie erhalten eine klare Antwort. Mit "schreibgeschützten" Attributen können Sie jedoch keine Änderungen an der CIA vornehmen. Sie können beispielsweise nicht telefonieren und plötzlich entscheiden , dass Kim Kardashian der Direktor sein soll oder dass Paris Hilton der Oberbefehlshaber sein soll.
Wenn Sie durch die Attribute Schreibzugriff erhalten, können Sie Änderungen vornehmen, wenn Sie möchten, auch wenn Sie sich außerhalb befinden. Ansonsten können Sie nur lesen.
Mit anderen Worten, mit Accessoren können Sie Anfragen an Organisationen stellen oder Änderungen vornehmen, die ansonsten keine externen Personen zulassen, je nachdem, ob es sich bei den Accessoren um Lese- oder Schreib-Accessoren handelt.
Objekte innerhalb einer Klasse können leicht aufeinander zugreifen
Genau das Gleiche gilt für Klassen und Ihre Fähigkeit, auf Variablen, Eigenschaften und Methoden in ihnen zuzugreifen. HTH! Fragen, bitte stellen und ich hoffe, ich kann klären.
quelle
Wenn Sie mit dem OOP-Konzept vertraut sind, müssen Sie mit der Getter- und Setter-Methode vertraut sein. attr_accessor macht dasselbe in Ruby.
Getter und Setter im Allgemeinen
Setter-Methode
Getter-Methode
Getter- und Setter-Methode in Ruby
quelle
Ich habe mich auch diesem Problem gestellt und eine etwas längere Antwort auf diese Frage geschrieben. Es gibt bereits einige gute Antworten darauf, aber jeder, der mehr Klarheit sucht, hoffe, dass meine Antwort helfen kann
Methode initialisieren
Mit "Initialisieren" können Sie beim Erstellen der Instanz Daten für eine Instanz eines Objekts festlegen, anstatt sie jedes Mal, wenn Sie eine neue Instanz der Klasse erstellen, in einer separaten Zeile in Ihrem Code festlegen zu müssen.
Im obigen Code setzen wir den Namen "Denis" mit der Initialisierungsmethode, indem wir Dennis durch den Parameter in Initialize übergeben. Wenn wir den Namen ohne die Initialisierungsmethode festlegen möchten, können wir dies folgendermaßen tun:
Im obigen Code legen wir den Namen fest, indem wir die Setter-Methode attr_accessor mit person.name aufrufen, anstatt die Werte bei der Initialisierung des Objekts festzulegen.
Beide „Methoden“, um diese Arbeit auszuführen, aber das Initialisieren spart uns Zeit und Codezeilen.
Dies ist die einzige Aufgabe zum Initialisieren. Sie können die Initialisierung nicht als Methode aufrufen. Um die Werte eines Instanzobjekts tatsächlich abzurufen, müssen Sie Getter und Setter (attr_reader (get), attr_writer (set) und attr_accessor (beide)) verwenden. Weitere Einzelheiten hierzu finden Sie weiter unten.
Getters, Setter (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: Der gesamte Zweck eines Getters besteht darin, den Wert einer bestimmten Instanzvariablen zurückzugeben. Besuchen Sie den folgenden Beispielcode, um eine Aufschlüsselung zu diesem Thema zu erhalten.
Im obigen Code rufen Sie die Methoden "item_name" und "Quantity" für die Instanz von Item "example" auf. Die "Puts example.item_name" und "example.quantity" geben den Wert für die Parameter zurück (oder "get"), die an das "example" übergeben wurden, und zeigen sie auf dem Bildschirm an.
Glücklicherweise gibt es in Ruby eine inhärente Methode, mit der wir diesen Code prägnanter schreiben können. die attr_reader-Methode. Siehe den Code unten;
Diese Syntax funktioniert genauso, nur dass wir sechs Codezeilen sparen. Stellen Sie sich vor, Sie hätten 5 weitere Status, die der Item-Klasse zugeordnet werden können? Der Code würde schnell lang werden.
Setter, attr_writer: Was mich anfangs mit Setter-Methoden beschäftigt hat, ist, dass es in meinen Augen eine identische Funktion wie die Initialisierungsmethode zu haben schien. Im Folgenden erkläre ich den Unterschied anhand meines Verständnisses.
Wie bereits erwähnt, können Sie mit der Initialisierungsmethode die Werte für eine Instanz eines Objekts bei der Objekterstellung festlegen.
Was aber, wenn Sie die Werte später nach dem Erstellen der Instanz festlegen oder nach der Initialisierung ändern möchten? Dies wäre ein Szenario, in dem Sie eine Setter-Methode verwenden würden. DAS IST DER UNTERSCHIED. Sie müssen keinen bestimmten Status festlegen, wenn Sie anfänglich die attr_writer-Methode verwenden.
Der folgende Code ist ein Beispiel für die Verwendung einer Setter-Methode, um den Wert item_name für diese Instanz der Item-Klasse zu deklarieren. Beachten Sie, dass wir weiterhin die Getter-Methode attr_reader verwenden, damit wir die Werte abrufen und auf dem Bildschirm drucken können, nur für den Fall, dass Sie den Code selbst testen möchten.
Der folgende Code ist ein Beispiel für die Verwendung von attr_writer, um unseren Code erneut zu verkürzen und Zeit zu sparen.
Der folgende Code ist eine Wiederholung des obigen Initialisierungsbeispiels, bei dem wir initialize verwenden, um den Objektwert von item_name bei der Erstellung festzulegen.
attr_accessor: Führt die Funktionen von attr_reader und attr_writer aus und spart Ihnen eine weitere Codezeile.
quelle
Ich denke, ein Teil dessen, was neue Rubyisten / Programmierer (wie mich) verwirrt, ist:
"Warum kann ich der Instanz nicht einfach sagen, dass sie ein bestimmtes Attribut (z. B. einen Namen) hat, und diesem Attribut auf einen Schlag einen Wert geben?"
Ein bisschen allgemeiner, aber so hat es für mich geklickt:
Gegeben:
Wir haben Person nicht als etwas definiert , das einen Namen oder andere Attribute für diese Angelegenheit haben kann.
Also wenn wir dann:
... und versuche ihnen einen Namen zu geben ...
Wir erhalten eine Fehlermeldung, weil in Rubyland eine Person-Objektklasse nicht mit einem "Namen" assoziiert ist oder einen solchen haben kann ... noch nicht!
ABER wir können jede der angegebenen Methoden verwenden (siehe vorherige Antworten), um zu sagen: "Eine Instanz einer Person-Klasse (
baby
) kann jetzt ein Attribut namens 'name' haben, daher haben wir nicht nur eine syntaktische Methode, um und zu erhalten diesen Namen setzen, aber es ist sinnvoll für uns, dies zu tun. "Wiederum diese Frage aus einem etwas anderen und allgemeineren Blickwinkel zu beantworten, aber ich hoffe, dies hilft der nächsten Instanz der Klasse Person, die ihren Weg zu diesem Thread findet.
quelle
Einfach ausgedrückt definiert es einen Setter und Getter für die Klasse.
Beachten Sie, dass
Damit
sind äquivalent, um einen Setter und einen Getter für die Klasse zu definieren.
quelle
Erstellt einfach
attr-accessor
die Methodengetter
undsetter
für die angegebenen Attributequelle
Eine andere Möglichkeit, dies zu verstehen, besteht darin, herauszufinden, welchen Fehlercode durch das Entfernen beseitigt wird
attr_accessor
.Beispiel:
Folgende Methoden stehen zur Verfügung:
Die folgenden Methoden lösen einen Fehler aus:
owner
undbalance
sind technisch gesehen keine Methode , sondern ein Attribut. Bankaccount - Klasse nicht habendef owner
unddef balance
. Wenn dies der Fall ist, können Sie die beiden folgenden Befehle verwenden. Aber diese beiden Methoden sind nicht da. Sie können jedoch auf Attribute zugreifen , als würden Sie über !! auf eine Methode zugreifen. Daher das Wort . Attribut. Accessor. Es greift auf Attribute zu, als würden Sie auf eine Methode zugreifen.attr_accessor
attr_accessor
Durch Hinzufügen
attr_accessor :balance, :owner
können Sie lesen und schreibenbalance
undowner
"Methode". Jetzt können Sie die letzten beiden Methoden verwenden.quelle
Definiert ein benanntes Attribut für dieses Modul, wobei der Name symbol.id2name lautet, und erstellt eine Instanzvariable (@name) und eine entsprechende Zugriffsmethode zum Lesen. Erstellt auch eine Methode namens name =, um das Attribut festzulegen.
quelle
Um ein Attribut Accessor alias attr_accessor zusammenzufassen, stehen Ihnen zwei kostenlose Methoden zur Verfügung.
Wie in Java werden sie Getter und Setter genannt.
Viele Antworten haben gute Beispiele gezeigt, deshalb werde ich mich nur kurz fassen.
#the_attribute
und
# the_attribute =
In den alten Ruby-Dokumenten bedeutet ein Hash-Tag # eine Methode. Es könnte auch ein Klassennamenpräfix enthalten ... MyClass # my_method
quelle
Ich bin neu in Ruby und musste mich nur mit dem Verständnis der folgenden Verrücktheit befassen. Könnte in Zukunft jemand anderem helfen. Am Ende ist es wie oben erwähnt, wo 2 Funktionen (def myvar, def myvar =) implizit für den Zugriff auf @myvar abgerufen werden, aber diese Methoden können durch lokale Deklarationen überschrieben werden.
quelle
Attribute und Zugriffsmethoden
Attribute sind Klassenkomponenten, auf die von außerhalb des Objekts zugegriffen werden kann. Sie sind in vielen anderen Programmiersprachen als Eigenschaften bekannt. Auf ihre Werte kann mithilfe der "Punktnotation" wie in object_name.attribute_name zugegriffen werden. Im Gegensatz zu Python und einigen anderen Sprachen erlaubt Ruby keinen direkten Zugriff auf Instanzvariablen von außerhalb des Objekts.
Im obigen Beispiel ist c eine Instanz (ein Objekt) der Car-Klasse. Wir haben erfolglos versucht, den Wert der Instanzvariablen der Räder von außerhalb des Objekts zu lesen. Was passiert ist, ist, dass Ruby versucht hat, eine Methode namens ribs innerhalb des c-Objekts aufzurufen, aber keine solche Methode wurde definiert. Kurz gesagt, object_name.attribute_name versucht, eine Methode namens attribute_name innerhalb des Objekts aufzurufen. Um von außen auf den Wert der Radvariablen zuzugreifen, müssen wir eine Instanzmethode mit diesem Namen implementieren, die beim Aufruf den Wert dieser Variablen zurückgibt. Das nennt man eine Accessor-Methode. Im allgemeinen Programmierkontext besteht die übliche Möglichkeit, von außerhalb des Objekts auf eine Instanzvariable zuzugreifen, darin, Zugriffsmethoden zu implementieren, die auch als Getter- und Setter-Methoden bezeichnet werden.
Im folgenden Beispiel haben wir der Car-Klasse Getter- und Setter-Methoden hinzugefügt, um von außerhalb des Objekts auf die Rädervariable zuzugreifen. Dies ist nicht die "Ruby-Methode", um Getter und Setter zu definieren. Es dient nur zur Veranschaulichung der Funktionsweise von Getter- und Setter-Methoden.
Das obige Beispiel funktioniert und ähnlicher Code wird häufig verwendet, um Getter- und Setter-Methoden in anderen Sprachen zu erstellen. Ruby bietet jedoch eine einfachere Möglichkeit, dies zu tun: drei integrierte Methoden namens attr_reader, attr_writer und attr_acessor. Die attr_reader-Methode macht eine Instanzvariable von außen lesbar, attr_writer macht sie beschreibbar und attr_acessor macht sie lesbar und beschreibbar.
Das obige Beispiel kann so umgeschrieben werden.
Im obigen Beispiel ist das Attribut "Räder" von außerhalb des Objekts lesbar und beschreibbar. Wenn wir anstelle von attr_accessor attr_reader verwenden würden, wäre dies schreibgeschützt. Wenn wir attr_writer verwenden würden, wäre es schreibgeschützt. Diese drei Methoden sind an sich keine Getter und Setter, aber wenn sie aufgerufen werden, erstellen sie Getter- und Setter-Methoden für uns. Dies sind Methoden, die dynamisch (programmgesteuert) andere Methoden generieren. Das nennt man Metaprogrammierung.
Das erste (längere) Beispiel, in dem Rubys integrierte Methoden nicht verwendet werden, sollte nur verwendet werden, wenn in den Getter- und Setter-Methoden zusätzlicher Code erforderlich ist. Beispielsweise muss eine Setter-Methode möglicherweise Daten validieren oder Berechnungen durchführen, bevor einer Instanzvariablen ein Wert zugewiesen wird.
Mit den integrierten Methoden instance_variable_get und instance_variable_set können Sie von außerhalb des Objekts auf Instanzvariablen zugreifen (diese lesen und schreiben). Dies ist jedoch selten zu rechtfertigen und in der Regel eine schlechte Idee, da die Umgehung der Kapselung dazu neigt, alle Arten von Chaos zu verursachen.
quelle
Hmmm. Viele gute Antworten. Hier sind meine paar Cent drauf.
attr_accessor
ist eine einfache Methode, die uns beim Reinigen ( TROCKNEN ) der Wiederholungsmethodengetter and setter
hilft .Damit wir uns mehr auf das Schreiben von Geschäftslogik konzentrieren können und uns nicht um die Setter und Getter kümmern müssen.
quelle
Die Hauptfunktionalität von attr_accessor gegenüber den anderen ist die Möglichkeit, auf Daten aus anderen Dateien zuzugreifen.
Normalerweise haben Sie attr_reader oder attr_writer, aber die gute Nachricht ist, dass Sie mit Ruby diese beiden mit attr_accessor kombinieren können. Ich betrachte es als meine To-Go-Methode, weil es runder oder vielseitiger ist. Denken Sie auch daran, dass dies in Rails beseitigt ist, da es im Back-End für Sie erledigt wird. Mit anderen Worten: Sie sind besser dran, attr_acessor gegenüber den beiden anderen zu verwenden, da Sie sich keine Sorgen machen müssen, dass Sie zu spezifisch sind. Der Accessor deckt alles ab. Ich weiß, dass dies eher eine allgemeine Erklärung ist, aber es hat mir als Anfänger geholfen.
Hoffe das hat geholfen!
quelle