web-dev-qa-db-fra.com

Mélange d'attr_accessor et d'une méthode d'initialisation dans une classe

Je vois du code comme:

class Person
  def initialize(name)
    @name = name
  end
end

Je comprends que cela me permet de faire des choses comme person = Person.new Et d'utiliser @name Ailleurs dans ma classe comme d'autres méthodes. Ensuite, j'ai vu du code comme:

class Person
  attr_accessor :name
end

...

person = Person.new
person.name = "David"

Je suis juste perdu avec ces deux méthodes de maillage. Quelles sont les utilisations particulières de def initialize(name)? Je suppose que attr_accessor Me permet de lire et d'écrire. Cela implique qu'il s'agit de deux méthodes distinctes. Oui? Vous voulez des éclaircissements sur def initialize Et attr_accessor Et sur la façon dont ils sont maillés.

22
David

initialize et attr_accessor n'ont rien à voir les uns avec les autres. attr_accessor :name crée deux méthodes:

def name
  @name
end

def name=(val)
  @name = val
end

Si vous souhaitez définir un nom lors de la création de l'objet, vous pouvez le faire dans l'initialiseur:

def initialize(name)
  @name = name
  # or
  # self.name = name
end

Mais vous n'êtes pas obligé de le faire. Vous pouvez définir le nom ultérieurement, après la création.

p = Person.new
p.name = "David"
puts p.name # >> "David"
25
Sergio Tulentsev

Voici la réponse que vous cherchez Classes and methods . Lisez-le attentivement.

Voici une bonne documentation du lien:

Classes et méthodes

Nous sommes maintenant prêts à créer notre propre classe d'adresses. Commençons simple. Commençons par une adresse qui ne contient que le champ "rue".

Voici comment définir une classe:

class Address
    def initialize(street)  
        @street = street 
    end
end

Passons par là:

  • Le mot-clé class définit une classe.

  • En définissant une méthode à l'intérieur de cette classe, nous l'associons à cette classe.

  • La méthode d'initialisation est ce qui construit réellement la structure de données. Chaque classe doit contenir une méthode d'initialisation.

@street est une variable objet. Similaire aux touches d'un hachage. Le signe @ distingue @street en tant que variable d'objet. Chaque fois que vous créez un objet de la classe Address, cet objet contiendra une variable @street.

Utilisons cette classe pour créer un objet d'adresse.

address = Addres.new("23 St George St.")  

C'est tout. l'adresse est maintenant un objet de la classe Adresse Lecture des données dans un objet

Supposons que nous voulons lire les données dans l'objet d'adresse. Pour ce faire, nous devons écrire une méthode qui renvoie ces données:

class Address
    def initialize(street)   
        @street = street 
    end

    # Just return @street
    def street
        @street
    end
end

Maintenant, la méthode Address # street vous permet de lire la rue de l'adresse. En irb:

>> address.street 
=> "23 St George St."

Une propriété d'un objet, visible à l'extérieur, est appelée attribut. Dans ce cas, la rue est un attribut. En particulier, il s'agit d'un attribut lisible. Étant donné que ce type d'attribut est très courant, Ruby vous propose un raccourci via le mot-clé attr_reader:

class Address
    attr_reader :street
    def initialize(street)   
        @street = street 
    end
end

Modification des données dans un objet

Nous pouvons également définir une méthode pour modifier les données d'un objet.

class Address
    attr_reader :street
    def initialize(street)  
        @street = street 
    end
    def street=(street)
        @street = street
    end
end

Ruby est assez intelligent dans son utilisation de la méthode street =:

`address.street = "45 Main St`."

Notez que vous pouvez mettre des espaces betten street et =. Maintenant que nous pouvons changer les données d'adresse, nous pouvons simplifier la méthode d'initialisation, et la faire simplement par défaut la rue à la chaîne vide "".

class Address
    attr_reader :street
    def initialize
        @street = ""
    end
    def street=(street)
        @street = street  
    end
end

address = Address.new
address.street = "23 St George St."

Cela peut ne pas sembler être une simplification, mais lorsque nous ajoutons les champs city, state et Zip, et plus de méthodes, cela rendra la définition de classe un peu plus simple.

Maintenant, la rue est également un attribut accessible en écriture. Comme précédemment, vous pouvez le déclarer comme tel avec attr_writer:

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end

Accès aux données

Très souvent, vous avez des attributs qui sont à la fois des attributs lisibles et inscriptibles. Ruby vous permet de les regrouper avec attr_accessor. Je suppose que ce serait appelé "attributs accessibles", mais je ne les ai jamais vus s'appeler ainsi.

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end

Avec cette connaissance, il est maintenant facile de définir la structure entière du carnet d'adresses. Il s'avère que attr_accessor et ses amis acceptent tous plusieurs arguments.

class Address
    attr_accessor :street, :city, :state, :Zip  
    def initialize
        @street = @city = @state = @Zip = ""
    end
end
17
Arup Rakshit

Je pense que vous considérez initialize comme un constructeur. Pour être précis, ce n'est pas le cas. Le constructeur par défaut est la méthode new sur la classe et initialize est appelée par cette méthode. Si vous ne définissez pas initialize, vous pouvez toujours créer un objet avec new car initialize n'est pas le constructeur lui-même. Dans ce cas, la valeur par défaut initialize ne fait rien. Si vous définissez initialize, cela est appelé juste après la création de l'objet.

La déclaration @foo = ... et attr_accessor :foo sont différents. Le premier attribue une valeur à la variable d'instance @foo, alors que ce dernier vous permet d'accéder à @foo via les méthodes foo et foo=. Sans ce dernier, vous pouvez toujours accéder à @foo en le décrivant directement.

6
sawa