Utilisation d'attributs avec du code Ruby

Regardez tout code orienté objet et tout cela suit plus ou moins le même schéma. Créez un objet, appelez des méthodes sur cet objet et accédez aux attributs de cet objet. Il n'y a pas grand-chose d'autre que vous pouvez faire avec un objet, sauf le passer en paramètre à la méthode d'un autre objet. Mais ce qui nous intéresse ici, ce sont les attributs.

Les attributs sont comme variables d'instance vous pouvez y accéder via la notation de point d'objet. Par exemple, nom d'une personne accéderait au nom d'une personne. De même, vous pouvez souvent attribuer des attributs comme person.name = "Alice". Il s'agit d'une fonctionnalité similaire aux variables membres (comme en C ++), mais pas tout à fait la même. Il n'y a rien de spécial ici, les attributs sont implémentés dans la plupart des langages à l'aide de "getters" et "setters", ou de méthodes qui récupèrent et définissent les attributs des variables d'instance.

Ruby ne fait pas de distinction entre les getters et setters d'attributs et les méthodes normales. En raison de la syntaxe d'appel de la méthode flexible de Ruby, aucune distinction ne doit être faite. Par exemple,

instagram viewer
nom d'une personne et nom d'une personne() sont la même chose, vous appelez le Nom avec zéro paramètre. L'un ressemble à un appel de méthode et l'autre ressemble à un attribut, mais ils sont vraiment tous les deux la même chose. Ils appellent tous les deux Nom méthode. De même, tout nom de méthode se terminant par un signe égal (=) peut être utilisé dans une affectation. La déclaration person.name = "Alice" c'est vraiment la même chose que person.name = (alice), même s'il y a un espace entre le nom de l'attribut et le signe égal, il s'agit toujours d'appeler le nom = méthode.

Vous pouvez facilement implémenter des attributs vous-même. En définissant les méthodes setter et getter, vous pouvez implémenter n'importe quel attribut que vous souhaitez. Voici un exemple de code implémentant le Nom attribut pour une classe de personne. Il stocke le nom dans un @Nom variable d'instance, mais le nom ne doit pas nécessairement être le même. Rappelez-vous, ces méthodes n'ont rien de spécial.

Vous remarquerez tout de suite que c'est beaucoup de travail. C'est beaucoup de frappe juste pour dire que vous voulez un attribut nommé Nom qui accède à la @Nom variable d'instance. Heureusement, Ruby fournit quelques méthodes pratiques qui définiront ces méthodes pour vous.

Il existe trois méthodes dans Module que vous pouvez utiliser à l'intérieur de vos déclarations de classe. N'oubliez pas que Ruby ne fait aucune distinction entre le runtime et le «temps de compilation», et tout code à l'intérieur des déclarations de classe peut non seulement définir des méthodes mais aussi appeler des méthodes. Appeler le attr_reader, attr_writer et attr_accessor Les méthodes définiront à leur tour les setters et les getters que nous nous définissions nous-mêmes dans la section précédente.

le attr_reader La méthode aime exactement ce qu'elle semble faire. Il prend n'importe quel nombre de paramètres de symbole et, pour chaque paramètre, définit une méthode "getter" qui retourne la variable d'instance du même nom. Nous pouvons donc remplacer notre Nom dans l'exemple précédent avec attr_reader: nom.

De même, le attr_writer définit une méthode "setter" pour chaque symbole qui lui est transmis. Notez que le signe égal ne doit pas nécessairement faire partie du symbole, seulement le nom de l'attribut. Nous pouvons remplacer le nom = méthode de l'exemple précédent avec un appel à attr_writier: nom.

Et, comme prévu, attr_accessor fait le travail des deux attr_writer et attr_reader. Si vous avez besoin à la fois d'un setter et d'un getter pour un attribut, il est courant de ne pas appeler les deux méthodes séparément et d'appeler à la place attr_accessor. Nous pourrions remplacer tous les deux le Nom et nom = méthodes de l'exemple précédent avec un seul appel à attr_accessor: nom.

Pourquoi devez-vous définir des setters manuellement? Pourquoi ne pas utiliser le attr_ * méthodes à chaque fois? Parce qu'ils cassent l'encapsulation. L'encapsulation est le principe qui stipule qu'aucune entité extérieure ne devrait avoir un accès illimité à l'état interne de votre objets. Tout doit être accessible à l'aide d'une interface qui empêche l'utilisateur de corrompre l'état interne de l'objet. En utilisant les méthodes ci-dessus, nous avons percé un grand trou dans notre mur d'encapsulation et permis de définir absolument n'importe quoi pour un nom, même évidemment des noms invalides.

Une chose que vous verrez souvent est que attr_reader sera utilisé pour définir rapidement un getter, mais un setter personnalisé sera défini car l'état interne de l'objet veut souvent être lis directement de l'état interne. Le passeur est ensuite défini manuellement et effectue des vérifications pour s'assurer que la valeur définie est logique. Ou, peut-être plus communément, aucun setter n'est défini du tout. Les autres méthodes de la fonction de classe définissent la variable d'instance derrière le getter d'une autre manière.

Nous pouvons maintenant ajouter un âge et mettre en œuvre correctement un Nom attribut. le âge L'attribut peut être défini dans la méthode constructeur, lu à l'aide de l'attribut âge getter mais seulement manipulé en utilisant le avoir_anniversaire, qui augmentera l'âge. le Nom L'attribut a un getter normal, mais le setter s'assure que le nom est en majuscule et se présente sous la forme de Prénom nom de famille.

instagram story viewer