Qu'est-ce que attr_accessor dans Ruby?

1024

J'ai du mal à comprendre attr_accessoren Ruby .
Quelqu'un peut m'expliquer cela?

dennismonsewicz
la source
1
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.

class Person
end

person = Person.new
person.name # => no method error

Évidemment, nous n'avons jamais défini de méthode name. Faisons cela.

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, 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.

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

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.

class Person
  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!

class Person
  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.

class Person
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"

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.

Max Chernyak
la source
46
@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:

  1. 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.

  2. 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".

Communauté
la source
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:

class Foo
  attr_accessor :bar
end

est équivalent à ce code:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end

Vous pouvez écrire ce type de méthode vous-même en 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
Phrogz
la source
3
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
end

def foo
  @foo
end

ce n'est rien de plus qu'un getter / setter pour un objet

efalcao
la source
10
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.

Tyler Eaves
la source
4
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:

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
Mandrin
la source
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.

BKSpurgeon
la source
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

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"

Méthode Setter

def name=(val)
  @name = val
end

Méthode Getter

def name
  @name
end

Méthode Getter et Setter en Ruby

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
Ahmed Eshaan
la source
2
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.

class Person

  def initialize(name)
    @name = name
  end


  def greeting
    "Hello #{@name}"
  end
end

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:

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

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.

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

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;

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

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.

class Item

attr_reader :item_name

  def item_name=(str)
    @item_name = (str)
  end

end

Le code ci-dessous est un exemple d'utilisation de attr_writer pour raccourcir à nouveau notre code et nous faire gagner du temps.

class Item

attr_reader :item_name
attr_writer :item_name

end

item = Item.new
puts item.item_name = "TV"

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.

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: exécute les fonctions à la fois d'attr_reader et d'attr_writer, vous permettant d'économiser une ligne de code supplémentaire.

Jbur43
la source
10

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é:

class Person
end

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.

Ben
la source
7

Autrement dit, il définira un setter et un getter pour la classe.

Notez que

attr_reader :v is equivalant to 
def v
  @v
end

attr_writer :v is equivalant to
def v=(value)
  @v=value
end

Donc

attr_accessor :v which means 
attr_reader :v; attr_writer :v 

sont équivalents pour définir un setter et un getter pour la classe.

Marcus Thornton
la source
5

Crée simplement attr-accessorles méthodes getteret setterpour les attributs spécifiés

Veeru
la source
5

Une autre façon de le comprendre est de comprendre quel code d'erreur il élimine en ayant attr_accessor .

Exemple:

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

Les méthodes suivantes sont disponibles:

$ bankie = BankAccout.new("Iggy")
$ bankie 
$ bankie.deposit(100)
$ bankie.withdraw(5)

Les méthodes suivantes génèrent une erreur:

$ bankie.owner     #undefined method `owner'... 
$ bankie.balance   #undefined method `balance'...

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.

$ bankie.balance
$ bankie.owner
Iggy
la source
2

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.

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]
Praveen_Shukla
la source
1

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

Douglas G. Allen
la source
1

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.

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
Adverbly
la source
0

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.

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>

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.

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

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.

class Car
  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.

BrunoFacca
la source
-2

Hmmm. Beaucoup de bonnes réponses. Voici mes quelques centimes dessus.

  • attr_accessorest 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.

Abibullah Rahamathulah
la source
-3

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é!

creativegeek
la source