Attr_accessor fonctionne-t-il de la même manière dans Git? Je trouve que certains tutoriels n'expliquent pas suffisamment et que d'autres supposent des connaissances préalables.
Angelfirenze
10
@Angelfirenze, gitn'a rien à voir avec attr_accessor. Git est un logiciel de contrôle de version, alors qu'il attr_accessors'agit d'une méthode dans Ruby .
Uzbekjon
Réponses:
2360
Disons que vous avez une classe Person.
classPersonend
person =Person.new
person.name # => no method error
Évidemment, nous n'avons jamais défini de méthode name. Faisons cela.
classPersondef name
@name# simply returning an instance variable @nameendend
person =Person.new
person.name # => nil
person.name ="Dennis"# => no method error
Aha, nous pouvons lire le nom, mais cela ne signifie pas que nous pouvons attribuer le nom. Ce sont deux méthodes différentes. Le premier est appelé lecteur et le second est appelé écrivain . Nous n'avons pas encore créé l'auteur alors faisons-le.
classPersondef name
@nameenddef name=(str)@name= str
endend
person =Person.new
person.name ='Dennis'
person.name # => "Dennis"
Impressionnant. Maintenant, nous pouvons écrire et lire la variable d'instance@name aide des méthodes de lecture et d'écriture. Sauf que cela se fait si souvent, pourquoi perdre du temps à écrire ces méthodes à chaque fois? Nous pouvons le faire plus facilement.
classPerson
attr_reader :name
attr_writer :name
end
Même cela peut devenir répétitif. Lorsque vous voulez à la fois lecteur et écrivain, utilisez simplement l'accesseur!
classPerson
attr_accessor :name
end
person =Person.new
person.name ="Dennis"
person.name # => "Dennis"
Fonctionne de la même manière! Et devinez quoi: la variable d'instance@name dans notre objet personne sera définie comme lorsque nous l'avons fait manuellement, vous pouvez donc l'utiliser dans d'autres méthodes.
C'est ça. Afin de comprendre comment attr_reader, attr_writeret les attr_accessorméthodes génèrent réellement des méthodes pour vous, lisez d'autres réponses, livres, ruby docs.
@hakunin - merci pour cette réponse claire. Ce qui me manque, c'est pourquoi la syntaxe Ruby suggère un deux-points ':' pour les variables d'instance dans l'instruction attr_ *? Il semble qu'il serait plus simple d'utiliser la même syntaxe '@' que celle utilisée ailleurs dans la classe pour faire référence à la variable.
Will
207
@WilliamSmith Pour répondre à votre question, vous devez comprendre qu'il attr_accessors'agit d'une méthode appelée sur la classe actuelle et d' :nameun paramètre que vous transmettez à cette méthode. Ce n'est pas une syntaxe spéciale, c'est un simple appel de méthode. Si vous deviez lui donner une @namevariable, cela n'aurait aucun sens, car @name contiendrait nil. Ce serait donc comme écrire attr_accessor nil. Vous ne lui passez pas une variable dont il a besoin pour créer, vous passez le nom que vous voulez que la variable soit appelée.
Max Chernyak
23
@hakunin - C'est tout à fait logique. Je viens d'apprendre aujourd'hui que ruby est en train de «fonctionner» lorsqu'il analyse un fichier et que chaque instruction et expression est en fait un appel de méthode sur un objet. Y compris attr_accessor. Très utile.
Will
52
utilisé Rails pendant 3 ans, je ne l'ai même jamais su. Honte
Sean Xiao
5
@Buminda oui, mais méthode nameet variable @namene sont pas la même chose. Ne les confondez pas. Vous avez une variable d'instance @namedans votre classe, et vous définissez attr_reader :namepour pouvoir la lire de l'extérieur. Sans, attr_readeril n'y a aucun moyen simple d'accéder à l' @nameextérieur de votre classe.
Max Chernyak
127
attr_accessor n'est qu'une méthode . (Le lien devrait fournir plus d'informations sur son fonctionnement - regardez les paires de méthodes générées et un didacticiel devrait vous montrer comment l'utiliser.)
L'astuce est que ce classn'est pas une définition en Ruby (c'est "juste une définition" dans des langages comme C ++ et Java), mais c'est une expression qui évalue . C'est au cours de cette évaluation que la attr_accessorméthode est invoquée, ce qui modifie à son tour la classe actuelle - rappelez-vous le récepteur implicite:, self.attr_accessoroù se selftrouve l'objet de classe "ouvert" à ce stade.
Le besoin attr_accessoret les amis, c'est bien:
Ruby, comme Smalltalk, n'autorise pas l'accès aux variables d'instance en dehors des méthodes 1 pour cet objet. Autrement dit, les variables d'instance ne sont pas accessibles sous la x.yforme comme cela est courant dans disons Java ou même Python. En Ruby yest toujours considéré comme un message à envoyer (ou "méthode à appeler"). Ainsi, les attr_*méthodes créent des wrappers qui procurent un @variableaccès à l'instance via des méthodes créées dynamiquement.
Boilerplate suce
J'espère que cela clarifie certains des petits détails. Codage heureux.
1 Ce n'est pas strictement vrai et il existe des "techniques" à ce sujet , mais il n'y a pas de prise en charge de la syntaxe pour l'accès aux "variables d'instance publique".
Lorsque vous dites que attr_accessor n'est "qu'une méthode", je comprends. Mais quelle est la syntaxe utilisée pour appeler cette méthode appelée? J'ai du mal à trouver la section de la documentation ruby qui parle de syntaxe comme some_method: name => "any",: notherName,: etc
BT
68
attr_accessorest (comme @pst l'a déclaré) juste une méthode. Ce qu'il fait, c'est créer plus de méthodes pour vous.
Donc, ce code ici:
classFoo
attr_accessor :bar
end
est équivalent à ce code:
classFoodef bar
@barenddef bar=( new_value )@bar= new_value
endend
Vous pouvez écrire ce type de méthode vous-même en Ruby:
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
C'est un excellent exemple de cas où la métaprogrammation est utilisée même dans les scénarios les plus débutants. Très agréable.
John Simon
2
Je cherchais une esquisse d'implémentation attr_accessoret enfin trouvée ici! Bien que cela ait résolu mon problème, mais je suis curieux de savoir où (livre / doc officiel) puis-je trouver un exemple d'implémentation comme celui-ci?
Wasif Hossain
40
attr_accessor est très simple:
attr_accessor :foo
est un raccourci pour:
def foo=(val)@foo= val
enddef foo
@fooend
ce n'est rien de plus qu'un getter / setter pour un objet
votre réponse est très bien. «Raccourci» signifie «un itinéraire alternatif plus court» selon mon dictionnaire, et non «sucre syntaxique» ou «macro interprété par l'interpréteur».
bowsersenior
25
Fondamentalement, ils falsifient des attributs de données accessibles au public, ce que Ruby n'a pas.
Bien que ce commentaire ne soit pas entièrement utile, il est vrai. Souligne le fait que les attributs de données publiques n'existent pas en dehors des méthodes "get" dans Ruby, ce qui est vraiment une information utile pour quelqu'un qui essaie d'apprendre la langue.
Eric Dand
3
Cela ne devrait vraiment pas être rétrogradé. En tant que gars non Ruby essayant de comprendre ces choses, cette réponse est très utile!
Brad
1
D'accord, semble très similaire au nom de C # {get; set;}
David Miler
17
C'est juste une méthode qui définit les méthodes getter et setter pour les variables d'instance. Un exemple de mise en œuvre serait:
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
gérer plusieurs attributs de cette manière est super!
Wasif Hossain
C'était un extrait de code très utile pour résoudre une autre question que j'avais liée à la métaprogrammation.
alexventuraio
15
Explication simple sans code
La plupart des réponses ci-dessus utilisent du code. Cette explication tente d'y répondre sans en utiliser aucune, via une analogie / histoire:
Les parties externes ne peuvent pas accéder aux secrets internes de la CIA
Imaginons un endroit vraiment secret: la CIA. Personne ne sait ce qui se passe dans la CIA, à part les gens à l'intérieur de la CIA. En d'autres termes, les personnes externes ne peuvent accéder à aucune information de la CIA. Mais parce qu'il n'est pas bon d'avoir une organisation qui est complètement secrète, certaines informations sont mises à la disposition du monde extérieur - seules choses que la CIA veut que tout le monde sache bien sûr: par exemple, le directeur de la CIA, à quel point ce département est respectueux de l'environnement à tous les autres départements du gouvernement, etc.
Si vous êtes en dehors de la CIA, vous ne pouvez accéder qu'aux informations qu'elle a mises à la disposition du public. Ou pour utiliser le langage de la CIA, vous ne pouvez accéder qu'aux informations "effacées".
Les informations que la CIA souhaite mettre à la disposition du grand public en dehors de la CIA sont appelées: attributs.
La signification des attributs de lecture et d'écriture:
Dans le cas de la CIA, la plupart des attributs sont en "lecture seule". Cela signifie que si vous êtes un parti extérieur à la CIA, vous pouvez demander: "qui est le directeur de la CIA?" et vous obtiendrez une réponse directe. Mais ce que vous ne pouvez pas faire avec les attributs "en lecture seule", c'est apporter des modifications dans la CIA. Par exemple, vous ne pouvez pas appeler et décider soudainement que vous voulez que Kim Kardashian soit le directeur, ou que vous voulez que Paris Hilton soit le commandant en chef.
Si les attributs vous ont donné un accès en "écriture", vous pouvez apporter des modifications si vous le souhaitez, même si vous étiez à l'extérieur. Sinon, la seule chose que vous pouvez faire est de lire.
En d'autres termes, les accesseurs vous permettent de poser des questions ou d'apporter des modifications aux organisations qui, autrement, ne laissent pas entrer de personnes externes, selon que les accesseurs sont des accesseurs en lecture ou en écriture.
Les objets à l'intérieur d'une classe peuvent facilement accéder les uns aux autres
D'un autre côté, si vous étiez déjà à l' intérieur de la CIA, vous pourriez facilement appeler votre agent de la CIA à Kaboul parce que cette information est facilement accessible étant donné que vous êtes déjà à l'intérieur. Mais si tu es dehors la CIA, vous n'aurez tout simplement pas accès: vous ne pourrez pas savoir qui ils sont (accès en lecture), et vous ne pourrez pas changer leur mission (accès en écriture).
Exactement la même chose avec les classes et votre capacité à accéder aux variables, propriétés et méthodes qu'elles contiennent. HTH! Toutes les questions, veuillez demander et j'espère que je peux clarifier.
Votre explication a du sens! +1 Désolé, êtes-vous sûr que l'expression "informations qui sont effacées par la CIA est correcte?
kouty
il existe différents niveaux de "clairance" dans la CIA: par exemple Top Secret (personne sauf le Prez), ou la confiance du public (tout le monde peut lire cette information). La CIA fournit en fait beaucoup de faits très sympas!
BKSpurgeon
Vous méritez le vote positif juste pour les exemples Kardashian, Paris Hilton :) Je pensais que c'était assez mauvais avec Trump pour le président, imaginez ces deux responsables omg!
rmcsharry
Oui! C'est ce dont nous avons besoin, StackOverflow sans code! :-)
Marvin
13
Si vous connaissez le concept OOP, vous devez vous familiariser avec la méthode getter et setter. attr_accessor fait de même en Ruby.
Getter et Setter dans General Way
classPersondef name
@nameenddef name=(str)@name= str
endend
person =Person.new
person.name ='Eshaan'
person.name # => "Eshaan"
Méthode Setter
def name=(val)@name= val
end
Méthode Getter
def name
@nameend
Méthode Getter et Setter en Ruby
classPerson
attr_accessor :name
end
person =Person.new
person.name ="Eshaan"
person.name # => "Eshaan"
explication parfaite! C'est un comportement très pratique et peut être remplacé trop facilement.
Rubyrider
12
J'ai également fait face à ce problème et j'ai écrit une réponse assez longue à cette question. Il y a déjà d'excellentes réponses à ce sujet, mais si vous cherchez plus de précisions, j'espère que ma réponse pourra vous aider.
Initialize, méthode
Initialize vous permet de définir des données sur une instance d'un objet lors de la création de l'instance plutôt que d'avoir à les définir sur une ligne distincte dans votre code chaque fois que vous créez une nouvelle instance de la classe.
classPersondef initialize(name)@name= name
enddef greeting
"Hello #{@name}"endend
person =Person.new("Denis")
puts person.greeting
Dans le code ci-dessus, nous définissons le nom «Denis» en utilisant la méthode initialize en passant Dennis à travers le paramètre dans Initialize. Si nous voulions définir le nom sans la méthode initialize, nous pourrions le faire comme ceci:
Dans le code ci-dessus, nous définissons le nom en appelant la méthode setter attr_accessor à l'aide de person.name, plutôt que de définir les valeurs lors de l'initialisation de l'objet.
Les deux «méthodes» de faire ce travail, mais initialiser nous font gagner du temps et des lignes de code.
C'est le seul travail d'initialisation. Vous ne pouvez pas appeler initialize comme méthode. Pour obtenir réellement les valeurs d'un objet d'instance, vous devez utiliser des getters et setters (attr_reader (get), attr_writer (set) et attr_accessor (both)). Voir ci-dessous pour plus de détails à ce sujet.
Getters, attr_reader: Le but d'un getter est de renvoyer la valeur d'une variable d'instance particulière. Consultez l'exemple de code ci-dessous pour une ventilation à ce sujet.
Dans le code ci-dessus, vous appelez les méthodes "item_name" et "quantity" sur l'instance de Item "example". Les «met example.item_name» et «example.quantity» renverront (ou «obtiendront») la valeur des paramètres qui ont été passés dans «l'exemple» et les afficheront à l'écran.
Heureusement, dans Ruby, il existe une méthode inhérente qui nous permet d'écrire ce code plus succinctement; la méthode attr_reader. Voir le code ci-dessous;
Cette syntaxe fonctionne exactement de la même manière, sauf qu'elle nous permet d'économiser six lignes de code. Imaginez si vous aviez 5 autres états attribuables à la classe Item? Le code deviendrait rapidement long.
Setters, attr_writer: Ce qui m'a d'abord traversé avec les méthodes setter, c'est qu'à mes yeux, il semblait remplir une fonction identique à la méthode initialize. Ci-dessous, j'explique la différence en fonction de ma compréhension;
Comme indiqué précédemment, la méthode initialize vous permet de définir les valeurs d'une instance d'un objet lors de sa création.
Mais que se passe-t-il si vous souhaitez définir les valeurs ultérieurement, après la création de l'instance, ou les modifier après leur initialisation? Ce serait un scénario où vous utiliseriez une méthode de définition. C'EST LA DIFFÉRENCE. Vous n'avez pas à «définir» un état particulier lorsque vous utilisez initialement la méthode attr_writer.
Le code ci-dessous est un exemple d'utilisation d'une méthode de définition pour déclarer la valeur item_name pour cette instance de la classe Item. Notez que nous continuons à utiliser la méthode getter attr_reader afin que nous puissions obtenir les valeurs et les imprimer à l'écran, juste au cas où vous voudriez tester le code par vous-même.
Le code ci-dessous est une réitération de l'exemple d'initialisation ci-dessus où nous utilisons initialize pour définir la valeur des objets de nom_article lors de la création.
Je pense qu'une partie de ce qui confond les nouveaux rubyistes / programmeurs (comme moi) est:
"Pourquoi ne puis-je pas simplement dire à l'instance qu'il a un attribut donné (par exemple, un nom) et donner à cet attribut une valeur tout d'un coup?"
Un peu plus généralisé, mais voici comment ça a cliqué pour moi:
Donné:
classPersonend
Nous n'avons pas défini Personne comme quelque chose qui peut avoir un nom ou tout autre attribut d'ailleurs.
Donc, si nous:
baby =Person.new
... et essayez de leur donner un nom ...
baby.name ="Ruth"
Nous obtenons une erreur parce que, dans Rubyland, une classe d'objet Personne n'est pas quelque chose qui est associée ou capable d'avoir un "nom" ... pour le moment!
MAIS nous pouvons utiliser n'importe laquelle des méthodes données (voir réponses précédentes) pour dire: "Une instance d'une classe Person ( baby) peut maintenant avoir un attribut appelé 'nom', donc nous avons non seulement une façon syntaxique d'obtenir et définir ce nom, mais il est logique pour nous de le faire. "
Encore une fois, frapper cette question sous un angle légèrement différent et plus général, mais j'espère que cela aidera la prochaine instance de la classe Person qui trouvera son chemin vers ce fil.
owneret balancene sont pas, techniquement, une méthode , mais un attribut. La classe BankAccount n'a pas def owneret def balance. Si c'est le cas, vous pouvez utiliser les deux commandes ci-dessous. Mais ces deux méthodes ne sont pas là. Cependant, vous pouvez accéder aux attributs comme si vous accédiez à une méthode via attr_accessor!! D'où le motattr_accessor . Attribut. Accesseur. Il accède aux attributs comme vous accéderiez à une méthode.
L'ajout attr_accessor :balance, :ownervous permet de lire et d'écrire balanceet de owner"méthode". Vous pouvez maintenant utiliser les 2 dernières méthodes.
Définit un attribut nommé pour ce module, où le nom est symbol.id2name, créant une variable d'instance (@name) et une méthode d'accès correspondante pour le lire. Crée également une méthode appelée nom = pour définir l'attribut.
Pour résumer un accesseur d'attribut aka attr_accessor vous donne deux méthodes gratuites.
Comme à Java, ils sont appelés getters et setters.
De nombreuses réponses ont montré de bons exemples, je vais donc être bref.
#the_attribute
et
# the_attribute =
Dans les anciens documents ruby, une balise de hachage # signifie une méthode. Il pourrait également inclure un préfixe de nom de classe ... MyClass # my_method
Je suis nouveau dans le rubis et je devais juste comprendre la bizarrerie suivante. Pourrait aider quelqu'un d'autre à l'avenir. Au final, c'est comme cela a été mentionné ci-dessus, où 2 fonctions (def myvar, def myvar =) obtiennent toutes deux implicitement l'accès à @myvar, mais ces méthodes peuvent être remplacées par des déclarations locales.
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
Les attributs sont des composants de classe accessibles depuis l'extérieur de l'objet. Ils sont connus comme propriétés dans de nombreux autres langages de programmation. Leurs valeurs sont accessibles en utilisant la "notation par points", comme dans nom_objet.nom_attribut. Contrairement à Python et à quelques autres langages, Ruby ne permet pas d'accéder directement aux variables d'instance depuis l'extérieur de l'objet.
classCardef initialize
@wheels=4# This is an instance variableendend
c =Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
Dans l'exemple ci-dessus, c est une instance (objet) de la classe Car. Nous avons essayé en vain de lire la valeur de la variable d'instance de roues depuis l'extérieur de l'objet. Ce qui s'est passé, c'est que Ruby a tenté d'appeler une méthode nommée roues dans l'objet c, mais aucune de ces méthodes n'a été définie. En bref, nom_objet.nom_attribut essaie d'appeler une méthode nommée nom_attribut dans l'objet. Pour accéder à la valeur de la variable roues de l'extérieur, nous devons implémenter une méthode d'instance de ce nom, qui renverra la valeur de cette variable lorsqu'elle sera appelée. C'est ce qu'on appelle une méthode d'accesseur. Dans le contexte général de programmation, la manière habituelle d'accéder à une variable d'instance depuis l'extérieur de l'objet est d'implémenter des méthodes d'accesseur, également appelées méthodes getter et setter.
Dans l'exemple suivant, nous avons ajouté des méthodes getter et setter à la classe Car pour accéder à la variable roues de l'extérieur de l'objet. Ce n'est pas la "manière Ruby" de définir les getters et setters; il sert uniquement à illustrer ce que font les méthodes getter et setter.
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
L'exemple ci-dessus fonctionne et un code similaire est couramment utilisé pour créer des méthodes getter et setter dans d'autres langues. Cependant, Ruby fournit un moyen plus simple de le faire: trois méthodes intégrées appelées attr_reader, attr_writer et attr_acessor. La méthode attr_reader rend une variable d'instance lisible de l'extérieur, attr_writer la rend accessible en écriture et attr_acessor la rend lisible et accessible en écriture.
L'exemple ci-dessus peut être réécrit comme ceci.
classCar
attr_accessor :wheels
end
f =Car.new
f.wheels =4
f.wheels # Output: => 4
Dans l'exemple ci-dessus, l'attribut roues sera lisible et inscriptible de l'extérieur de l'objet. Si au lieu de attr_accessor, nous avons utilisé attr_reader, ce serait en lecture seule. Si nous utilisions attr_writer, ce serait en écriture seule. Ces trois méthodes ne sont pas des getters et des setters en elles-mêmes mais, lorsqu'elles sont appelées, elles créent des méthodes getter et setter pour nous. Ce sont des méthodes qui génèrent dynamiquement (par programme) d'autres méthodes; cela s'appelle la métaprogrammation.
Le premier exemple (plus long), qui n'utilise pas les méthodes intégrées de Ruby, ne doit être utilisé que lorsqu'un code supplémentaire est requis dans les méthodes getter et setter. Par exemple, une méthode de définition peut avoir besoin de valider des données ou d'effectuer un calcul avant d'affecter une valeur à une variable d'instance.
Il est possible d'accéder (lire et écrire) aux variables d'instance depuis l'extérieur de l'objet, en utilisant les méthodes intégrées instance_variable_get et instance_variable_set. Cependant, cela est rarement justifiable et généralement une mauvaise idée, car le contournement de l'encapsulation a tendance à causer toutes sortes de ravages.
La fonctionnalité principale de attr_accessor par rapport aux autres est la capacité d'accéder aux données à partir d'autres fichiers.
Donc, vous auriez généralement attr_reader ou attr_writer mais la bonne nouvelle est que Ruby vous permet de combiner ces deux avec attr_accessor. Je pense que c'est ma méthode à emporter car elle est plus bien arrondie ou polyvalente. Aussi, gardez à l'esprit que dans Rails, cela est éliminé car il le fait pour vous dans le back-end. En d'autres termes: il vaut mieux utiliser attr_acessor par rapport aux deux autres parce que vous n'avez pas à vous soucier d'être précis, l'accesseur couvre tout cela. Je sais que c'est plus une explication générale mais cela m'a aidé en tant que débutant.
git
n'a rien à voir avecattr_accessor
. Git est un logiciel de contrôle de version, alors qu'ilattr_accessor
s'agit d'une méthode dans Ruby .Réponses:
Disons que vous avez une classe
Person
.Évidemment, nous n'avons jamais défini de méthode
name
. Faisons cela.Aha, nous pouvons lire le nom, mais cela ne signifie pas que nous pouvons attribuer le nom. Ce sont deux méthodes différentes. Le premier est appelé lecteur et le second est appelé écrivain . Nous n'avons pas encore créé l'auteur alors faisons-le.
Impressionnant. Maintenant, nous pouvons écrire et lire la variable d'instance
@name
aide des méthodes de lecture et d'écriture. Sauf que cela se fait si souvent, pourquoi perdre du temps à écrire ces méthodes à chaque fois? Nous pouvons le faire plus facilement.Même cela peut devenir répétitif. Lorsque vous voulez à la fois lecteur et écrivain, utilisez simplement l'accesseur!
Fonctionne de la même manière! Et devinez quoi: la variable d'instance
@name
dans notre objet personne sera définie comme lorsque nous l'avons fait manuellement, vous pouvez donc l'utiliser dans d'autres méthodes.C'est ça. Afin de comprendre comment
attr_reader
,attr_writer
et lesattr_accessor
méthodes génèrent réellement des méthodes pour vous, lisez d'autres réponses, livres, ruby docs.la source
attr_accessor
s'agit d'une méthode appelée sur la classe actuelle et d':name
un paramètre que vous transmettez à cette méthode. Ce n'est pas une syntaxe spéciale, c'est un simple appel de méthode. Si vous deviez lui donner une@name
variable, cela n'aurait aucun sens, car @name contiendraitnil
. Ce serait donc comme écrireattr_accessor nil
. Vous ne lui passez pas une variable dont il a besoin pour créer, vous passez le nom que vous voulez que la variable soit appelée.name
et variable@name
ne sont pas la même chose. Ne les confondez pas. Vous avez une variable d'instance@name
dans votre classe, et vous définissezattr_reader :name
pour pouvoir la lire de l'extérieur. Sans,attr_reader
il n'y a aucun moyen simple d'accéder à l'@name
extérieur de votre classe.attr_accessor n'est qu'une méthode . (Le lien devrait fournir plus d'informations sur son fonctionnement - regardez les paires de méthodes générées et un didacticiel devrait vous montrer comment l'utiliser.)
L'astuce est que ce
class
n'est pas une définition en Ruby (c'est "juste une définition" dans des langages comme C ++ et Java), mais c'est une expression qui évalue . C'est au cours de cette évaluation que laattr_accessor
méthode est invoquée, ce qui modifie à son tour la classe actuelle - rappelez-vous le récepteur implicite:,self.attr_accessor
où seself
trouve l'objet de classe "ouvert" à ce stade.Le besoin
attr_accessor
et les amis, c'est bien:Ruby, comme Smalltalk, n'autorise pas l'accès aux variables d'instance en dehors des méthodes 1 pour cet objet. Autrement dit, les variables d'instance ne sont pas accessibles sous la
x.y
forme comme cela est courant dans disons Java ou même Python. En Rubyy
est toujours considéré comme un message à envoyer (ou "méthode à appeler"). Ainsi, lesattr_*
méthodes créent des wrappers qui procurent un@variable
accès à l'instance via des méthodes créées dynamiquement.Boilerplate suce
J'espère que cela clarifie certains des petits détails. Codage heureux.
1 Ce n'est pas strictement vrai et il existe des "techniques" à ce sujet , mais il n'y a pas de prise en charge de la syntaxe pour l'accès aux "variables d'instance publique".
la source
attr_accessor
est (comme @pst l'a déclaré) juste une méthode. Ce qu'il fait, c'est créer plus de méthodes pour vous.Donc, ce code ici:
est équivalent à ce code:
Vous pouvez écrire ce type de méthode vous-même en Ruby:
la source
attr_accessor
et enfin trouvée ici! Bien que cela ait résolu mon problème, mais je suis curieux de savoir où (livre / doc officiel) puis-je trouver un exemple d'implémentation comme celui-ci?attr_accessor
est très simple:est un raccourci pour:
ce n'est rien de plus qu'un getter / setter pour un objet
la source
Fondamentalement, ils falsifient des attributs de données accessibles au public, ce que Ruby n'a pas.
la source
C'est juste une méthode qui définit les méthodes getter et setter pour les variables d'instance. Un exemple de mise en œuvre serait:
la source
Explication simple sans code
La plupart des réponses ci-dessus utilisent du code. Cette explication tente d'y répondre sans en utiliser aucune, via une analogie / histoire:
Les parties externes ne peuvent pas accéder aux secrets internes de la CIA
Imaginons un endroit vraiment secret: la CIA. Personne ne sait ce qui se passe dans la CIA, à part les gens à l'intérieur de la CIA. En d'autres termes, les personnes externes ne peuvent accéder à aucune information de la CIA. Mais parce qu'il n'est pas bon d'avoir une organisation qui est complètement secrète, certaines informations sont mises à la disposition du monde extérieur - seules choses que la CIA veut que tout le monde sache bien sûr: par exemple, le directeur de la CIA, à quel point ce département est respectueux de l'environnement à tous les autres départements du gouvernement, etc.
Si vous êtes en dehors de la CIA, vous ne pouvez accéder qu'aux informations qu'elle a mises à la disposition du public. Ou pour utiliser le langage de la CIA, vous ne pouvez accéder qu'aux informations "effacées".
Les informations que la CIA souhaite mettre à la disposition du grand public en dehors de la CIA sont appelées: attributs.
La signification des attributs de lecture et d'écriture:
Dans le cas de la CIA, la plupart des attributs sont en "lecture seule". Cela signifie que si vous êtes un parti extérieur à la CIA, vous pouvez demander: "qui est le directeur de la CIA?" et vous obtiendrez une réponse directe. Mais ce que vous ne pouvez pas faire avec les attributs "en lecture seule", c'est apporter des modifications dans la CIA. Par exemple, vous ne pouvez pas appeler et décider soudainement que vous voulez que Kim Kardashian soit le directeur, ou que vous voulez que Paris Hilton soit le commandant en chef.
Si les attributs vous ont donné un accès en "écriture", vous pouvez apporter des modifications si vous le souhaitez, même si vous étiez à l'extérieur. Sinon, la seule chose que vous pouvez faire est de lire.
En d'autres termes, les accesseurs vous permettent de poser des questions ou d'apporter des modifications aux organisations qui, autrement, ne laissent pas entrer de personnes externes, selon que les accesseurs sont des accesseurs en lecture ou en écriture.
Les objets à l'intérieur d'une classe peuvent facilement accéder les uns aux autres
Exactement la même chose avec les classes et votre capacité à accéder aux variables, propriétés et méthodes qu'elles contiennent. HTH! Toutes les questions, veuillez demander et j'espère que je peux clarifier.
la source
Si vous connaissez le concept OOP, vous devez vous familiariser avec la méthode getter et setter. attr_accessor fait de même en Ruby.
Getter et Setter dans General Way
Méthode Setter
Méthode Getter
Méthode Getter et Setter en Ruby
la source
J'ai également fait face à ce problème et j'ai écrit une réponse assez longue à cette question. Il y a déjà d'excellentes réponses à ce sujet, mais si vous cherchez plus de précisions, j'espère que ma réponse pourra vous aider.
Initialize, méthode
Initialize vous permet de définir des données sur une instance d'un objet lors de la création de l'instance plutôt que d'avoir à les définir sur une ligne distincte dans votre code chaque fois que vous créez une nouvelle instance de la classe.
Dans le code ci-dessus, nous définissons le nom «Denis» en utilisant la méthode initialize en passant Dennis à travers le paramètre dans Initialize. Si nous voulions définir le nom sans la méthode initialize, nous pourrions le faire comme ceci:
Dans le code ci-dessus, nous définissons le nom en appelant la méthode setter attr_accessor à l'aide de person.name, plutôt que de définir les valeurs lors de l'initialisation de l'objet.
Les deux «méthodes» de faire ce travail, mais initialiser nous font gagner du temps et des lignes de code.
C'est le seul travail d'initialisation. Vous ne pouvez pas appeler initialize comme méthode. Pour obtenir réellement les valeurs d'un objet d'instance, vous devez utiliser des getters et setters (attr_reader (get), attr_writer (set) et attr_accessor (both)). Voir ci-dessous pour plus de détails à ce sujet.
Getters, Setters (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: Le but d'un getter est de renvoyer la valeur d'une variable d'instance particulière. Consultez l'exemple de code ci-dessous pour une ventilation à ce sujet.
Dans le code ci-dessus, vous appelez les méthodes "item_name" et "quantity" sur l'instance de Item "example". Les «met example.item_name» et «example.quantity» renverront (ou «obtiendront») la valeur des paramètres qui ont été passés dans «l'exemple» et les afficheront à l'écran.
Heureusement, dans Ruby, il existe une méthode inhérente qui nous permet d'écrire ce code plus succinctement; la méthode attr_reader. Voir le code ci-dessous;
Cette syntaxe fonctionne exactement de la même manière, sauf qu'elle nous permet d'économiser six lignes de code. Imaginez si vous aviez 5 autres états attribuables à la classe Item? Le code deviendrait rapidement long.
Setters, attr_writer: Ce qui m'a d'abord traversé avec les méthodes setter, c'est qu'à mes yeux, il semblait remplir une fonction identique à la méthode initialize. Ci-dessous, j'explique la différence en fonction de ma compréhension;
Comme indiqué précédemment, la méthode initialize vous permet de définir les valeurs d'une instance d'un objet lors de sa création.
Mais que se passe-t-il si vous souhaitez définir les valeurs ultérieurement, après la création de l'instance, ou les modifier après leur initialisation? Ce serait un scénario où vous utiliseriez une méthode de définition. C'EST LA DIFFÉRENCE. Vous n'avez pas à «définir» un état particulier lorsque vous utilisez initialement la méthode attr_writer.
Le code ci-dessous est un exemple d'utilisation d'une méthode de définition pour déclarer la valeur item_name pour cette instance de la classe Item. Notez que nous continuons à utiliser la méthode getter attr_reader afin que nous puissions obtenir les valeurs et les imprimer à l'écran, juste au cas où vous voudriez tester le code par vous-même.
Le code ci-dessous est un exemple d'utilisation de attr_writer pour raccourcir à nouveau notre code et nous faire gagner du temps.
Le code ci-dessous est une réitération de l'exemple d'initialisation ci-dessus où nous utilisons initialize pour définir la valeur des objets de nom_article lors de la création.
attr_accessor: exécute les fonctions à la fois d'attr_reader et d'attr_writer, vous permettant d'économiser une ligne de code supplémentaire.
la source
Je pense qu'une partie de ce qui confond les nouveaux rubyistes / programmeurs (comme moi) est:
"Pourquoi ne puis-je pas simplement dire à l'instance qu'il a un attribut donné (par exemple, un nom) et donner à cet attribut une valeur tout d'un coup?"
Un peu plus généralisé, mais voici comment ça a cliqué pour moi:
Donné:
Nous n'avons pas défini Personne comme quelque chose qui peut avoir un nom ou tout autre attribut d'ailleurs.
Donc, si nous:
... et essayez de leur donner un nom ...
Nous obtenons une erreur parce que, dans Rubyland, une classe d'objet Personne n'est pas quelque chose qui est associée ou capable d'avoir un "nom" ... pour le moment!
MAIS nous pouvons utiliser n'importe laquelle des méthodes données (voir réponses précédentes) pour dire: "Une instance d'une classe Person (
baby
) peut maintenant avoir un attribut appelé 'nom', donc nous avons non seulement une façon syntaxique d'obtenir et définir ce nom, mais il est logique pour nous de le faire. "Encore une fois, frapper cette question sous un angle légèrement différent et plus général, mais j'espère que cela aidera la prochaine instance de la classe Person qui trouvera son chemin vers ce fil.
la source
Autrement dit, il définira un setter et un getter pour la classe.
Notez que
Donc
sont équivalents pour définir un setter et un getter pour la classe.
la source
Crée simplement
attr-accessor
les méthodesgetter
etsetter
pour les attributs spécifiésla source
Une autre façon de le comprendre est de comprendre quel code d'erreur il élimine en ayant
attr_accessor
.Exemple:
Les méthodes suivantes sont disponibles:
Les méthodes suivantes génèrent une erreur:
owner
etbalance
ne sont pas, techniquement, une méthode , mais un attribut. La classe BankAccount n'a pasdef owner
etdef balance
. Si c'est le cas, vous pouvez utiliser les deux commandes ci-dessous. Mais ces deux méthodes ne sont pas là. Cependant, vous pouvez accéder aux attributs comme si vous accédiez à une méthode viaattr_accessor
!! D'où le motattr_accessor
. Attribut. Accesseur. Il accède aux attributs comme vous accéderiez à une méthode.L'ajout
attr_accessor :balance, :owner
vous permet de lire et d'écrirebalance
et deowner
"méthode". Vous pouvez maintenant utiliser les 2 dernières méthodes.la source
Définit un attribut nommé pour ce module, où le nom est symbol.id2name, créant une variable d'instance (@name) et une méthode d'accès correspondante pour le lire. Crée également une méthode appelée nom = pour définir l'attribut.
la source
Pour résumer un accesseur d'attribut aka attr_accessor vous donne deux méthodes gratuites.
Comme à Java, ils sont appelés getters et setters.
De nombreuses réponses ont montré de bons exemples, je vais donc être bref.
#the_attribute
et
# the_attribute =
Dans les anciens documents ruby, une balise de hachage # signifie une méthode. Il pourrait également inclure un préfixe de nom de classe ... MyClass # my_method
la source
Je suis nouveau dans le rubis et je devais juste comprendre la bizarrerie suivante. Pourrait aider quelqu'un d'autre à l'avenir. Au final, c'est comme cela a été mentionné ci-dessus, où 2 fonctions (def myvar, def myvar =) obtiennent toutes deux implicitement l'accès à @myvar, mais ces méthodes peuvent être remplacées par des déclarations locales.
la source
Attributs et méthodes d'accesseur
Les attributs sont des composants de classe accessibles depuis l'extérieur de l'objet. Ils sont connus comme propriétés dans de nombreux autres langages de programmation. Leurs valeurs sont accessibles en utilisant la "notation par points", comme dans nom_objet.nom_attribut. Contrairement à Python et à quelques autres langages, Ruby ne permet pas d'accéder directement aux variables d'instance depuis l'extérieur de l'objet.
Dans l'exemple ci-dessus, c est une instance (objet) de la classe Car. Nous avons essayé en vain de lire la valeur de la variable d'instance de roues depuis l'extérieur de l'objet. Ce qui s'est passé, c'est que Ruby a tenté d'appeler une méthode nommée roues dans l'objet c, mais aucune de ces méthodes n'a été définie. En bref, nom_objet.nom_attribut essaie d'appeler une méthode nommée nom_attribut dans l'objet. Pour accéder à la valeur de la variable roues de l'extérieur, nous devons implémenter une méthode d'instance de ce nom, qui renverra la valeur de cette variable lorsqu'elle sera appelée. C'est ce qu'on appelle une méthode d'accesseur. Dans le contexte général de programmation, la manière habituelle d'accéder à une variable d'instance depuis l'extérieur de l'objet est d'implémenter des méthodes d'accesseur, également appelées méthodes getter et setter.
Dans l'exemple suivant, nous avons ajouté des méthodes getter et setter à la classe Car pour accéder à la variable roues de l'extérieur de l'objet. Ce n'est pas la "manière Ruby" de définir les getters et setters; il sert uniquement à illustrer ce que font les méthodes getter et setter.
L'exemple ci-dessus fonctionne et un code similaire est couramment utilisé pour créer des méthodes getter et setter dans d'autres langues. Cependant, Ruby fournit un moyen plus simple de le faire: trois méthodes intégrées appelées attr_reader, attr_writer et attr_acessor. La méthode attr_reader rend une variable d'instance lisible de l'extérieur, attr_writer la rend accessible en écriture et attr_acessor la rend lisible et accessible en écriture.
L'exemple ci-dessus peut être réécrit comme ceci.
Dans l'exemple ci-dessus, l'attribut roues sera lisible et inscriptible de l'extérieur de l'objet. Si au lieu de attr_accessor, nous avons utilisé attr_reader, ce serait en lecture seule. Si nous utilisions attr_writer, ce serait en écriture seule. Ces trois méthodes ne sont pas des getters et des setters en elles-mêmes mais, lorsqu'elles sont appelées, elles créent des méthodes getter et setter pour nous. Ce sont des méthodes qui génèrent dynamiquement (par programme) d'autres méthodes; cela s'appelle la métaprogrammation.
Le premier exemple (plus long), qui n'utilise pas les méthodes intégrées de Ruby, ne doit être utilisé que lorsqu'un code supplémentaire est requis dans les méthodes getter et setter. Par exemple, une méthode de définition peut avoir besoin de valider des données ou d'effectuer un calcul avant d'affecter une valeur à une variable d'instance.
Il est possible d'accéder (lire et écrire) aux variables d'instance depuis l'extérieur de l'objet, en utilisant les méthodes intégrées instance_variable_get et instance_variable_set. Cependant, cela est rarement justifiable et généralement une mauvaise idée, car le contournement de l'encapsulation a tendance à causer toutes sortes de ravages.
la source
Hmmm. Beaucoup de bonnes réponses. Voici mes quelques centimes dessus.
attr_accessor
est une méthode simple qui nous aide à nettoyer ( SÉCHAGE ) les méthodes répétitivesgetter and setter
.Afin que nous puissions nous concentrer davantage sur l'écriture de la logique métier et ne pas nous soucier des setters et des getters.
la source
La fonctionnalité principale de attr_accessor par rapport aux autres est la capacité d'accéder aux données à partir d'autres fichiers.
Donc, vous auriez généralement attr_reader ou attr_writer mais la bonne nouvelle est que Ruby vous permet de combiner ces deux avec attr_accessor. Je pense que c'est ma méthode à emporter car elle est plus bien arrondie ou polyvalente. Aussi, gardez à l'esprit que dans Rails, cela est éliminé car il le fait pour vous dans le back-end. En d'autres termes: il vaut mieux utiliser attr_acessor par rapport aux deux autres parce que vous n'avez pas à vous soucier d'être précis, l'accesseur couvre tout cela. Je sais que c'est plus une explication générale mais cela m'a aidé en tant que débutant.
J'espère que cela vous a aidé!
la source