Utilisation de variables d’instance dans les méthodes de classe – Ruby

Je suis très nouveau sur Ruby (je suis en fait c # dev.), Alors cette question pourrait être un noob. J’ai une classe quelque chose comme ci-dessous, et j’ai utilisé des variables d’instance (tableau) pour éviter d’utiliser beaucoup de parameters de méthode.

Cela fonctionne comme prévu, mais est-ce une bonne pratique à faire? En fait, je ne m’attendrais pas à ce que cela fonctionne, mais je suppose que les méthodes de classe ne fonctionnent pas comme des méthodes statiques dans d’autres langages, alors je me demande si c’est une bonne pratique ou si tout est en place

class DummyClass def self.dummy_method1 @arr = [] # Play with that array end def self.dummy_method2 # use @arr for something else end end 

Les variables d’instance de raison fonctionnent sur les classes dans Ruby: les classes Ruby sont des instances elles-mêmes (instances de la classe Class ). Essayez-le vous-même en inspectant DummyClass.class . Il n’y a pas de “méthodes statiques” dans le sens C # dans Ruby car chaque méthode est définie sur (ou héritée dans) une instance et appelée sur une instance. En conséquence, ils peuvent accéder aux variables d’instance disponibles sur l’appelé.

Étant donné que DummyClass est une instance, ses propres variables d’instance peuvent DummyClass s’inscrire. Vous pouvez même accéder à ces variables d’instance tant que vous avez une référence à la classe (ce qui devrait toujours être parce que les noms de classes sont des constantes). À tout moment, vous pourrez appeler ::DummyClass.instance_variable_get(:@arr) et obtenir la valeur actuelle de cette variable d’instance.

Quant à savoir si c’est une bonne chose à faire, cela dépend des méthodes .

Si @arr est logiquement “l’état” de l’instance / classe DummyClass , stockez-le dans la variable d’instance. Si @arr n’est utilisé que dans dummy_method2 comme raccourci opérationnel, transmettez-le comme argument. Pour donner un exemple où l’approche de la variable d’instance est utilisée, considérez ActiveRecord dans Rails. Cela vous permet de faire ceci:

 u = User.new u.name = "foobar" u.save 

Ici, le nom qui a été atsortingbué à l’utilisateur est une donnée légitime pour l’utilisateur. Si, avant l’appel à #save , on devait demander “quel est le nom de l’utilisateur à ce stade”, vous répondriez “foobar”. Si vous creusez assez loin dans les composants internes (vous allez creuser très loin et dans beaucoup de métaprogrammation, vous verrez qu’ils utilisent des variables d’instance exactement pour cela).

L’exemple que j’ai utilisé contient deux appels publics distincts. Pour voir un cas où les variables d’instance sont encore utilisées malgré un seul appel, consultez l’implémentation ActiveRecord de #update_atsortingbutes . Le corps de la méthode est simplement load(atsortingbutes, false) && save . Pourquoi #save ne reçoit-il aucun argument (comme le nouveau name ) même s’il sera dans le corps de save où quelque chose comme UPDATE users SET name='foobar' WHERE id=1; ? C’est parce que des choses comme le nom sont des informations qui appartiennent à l’instance.

Inversement, nous pouvons examiner un cas où les variables d’instance n’auraient aucun sens à utiliser. Examinez l’implémentation de #link_to_if , une méthode qui accepte un argument boolean-ish (généralement une expression dans le code source), ainsi que les arguments généralement acceptés par #link_to tels que l’URL à laquelle #link_to . Lorsque la condition booléenne est véridique, il doit transmettre le rest des arguments à #link_to et l’invoquer. Il ne serait pas logique d’atsortingbuer des variables d’instance ici parce que vous ne diriez pas que le contexte invoquant ici (le moteur de rendu) contient ces informations dans l’instance. Le moteur de rendu lui-même ne dispose pas d’une “URL vers laquelle se lier” et, par conséquent, il ne doit pas être enterré dans une variable d’instance.

Ce sont des variables d’instance de classe et sont des choses parfaitement légitimes dans ruby: les classes sont aussi des objects (instances de Class) et ont donc des variables d’instance.

Une chose à surveiller est que chaque sous-classe aura son propre ensemble de variables d’instance de classe (après que tous ces objects soient différents): Si vous avez sous- DummyClass , les méthodes de classe de la sous-classe ne pourront pas voir @arr .

Les variables de classe ( @@foo ) sont bien sûr inverses: la hiérarchie de classe entière partage les mêmes variables de classe.