Quelle est la meilleure façon de résumer ce modèle:
class MyClass attr_accessor :foo, :bar def initialize(foo, bar) @foo, @bar = foo, bar end end
5 Réponses :
C'est la première solution qui me vient à l'esprit. Il y a un gros inconvénient dans mon module: vous devez définir la méthode d'initialisation de la classe avant d'inclure le module ou cela ne fonctionnera pas.
Il y a probablement une meilleure solution pour ce problème, mais c'est ce que j'ai écrit en moins de deux minutes. P>
En outre, je n'ai pas eu trop de performances. Vous pouvez probablement trouver une bien meilleure solution que moi, surtout parler de performances. ;) p>
Je rejette à peu près cette solution hors de la main pour la dépendance de l'activesupport. Toute dépendance pour ce type de chose serait indésirable, mais obligeant que la bibliothèque de rubs rubis odieux autour de viennent juste une insulte à la blessure.
J'ai utilisé ActiveSupport juste pour profiter de alias_method_chain, mais vous n'en avez pas besoin du tout. Vous pouvez utiliser des alias.
Une solution à ce problème déjà (partiellement) Existe , mais Si vous souhaitez une approche plus déclarative dans vos classes, les suivants doivent fonctionner. Vous pouvez maintenant faire: P> Si vous souhaitez créer une solution avec une performance minimale absolue, il ne serait pas si difficile de refacteur la plupart em> de la fonctionnalité dans une chaîne qui peut être Remarque: j'ai trouvé que le piratage class MyClass < ParentClass
initialize_with :foo, :bar
def initialize(baz)
@initialized = true
super(baz) # pass any arguments to initializer of superclass
end
end
my_obj = MyClass.new "foo", "bar", "baz"
my_obj.foo #=> "foo"
my_obj.bar #=> "bar"
my_obj.instance_variable_get(:@initialized) #=> true
initialize_with code> li>
initialiser code> pour effectuer une initialisation personnalisée li>
super code> dans
initialiser code> li>
Initialiser CODE> sont les arguments qui n'ont pas été consommés par des attributs spécifiés avec
initialize_with code> li>
initialisze_with code> sont hérités, mais la définition d'un nouvel ensemble sur une classe enfant supprimera les attributs parent li>
eval ED lorsque l'initialiseur est défini. Je n'ai pas comparé quelle est la différence. P>
nouveau code> fonctionne mieux que le piratage
initialiser code>. Si vous définissez
initialiser code> avec métaprogramming, vous obtiendrez probablement un scénario dans lequel vous passez un bloc à
initialize_with code> comme initialisateur de substitution, et il n'est pas possible d'utiliser
super code> dans un bloc. p> p>
Cette solution a l'air assez bien. Il semble que vous puissiez appeler Zsuper (Super sans parens ni arguments), c'est-à-dire super au lieu de Super (Baz). J'aimerais certainement voir une solution qui n'a pas besoin de définir_method et que vous pourriez éviter d'utiliser instance_variable_set. Comme vous l'avez souligné, cela nécessiterait probablement des chaînes eval.
J'accepte cette solution même s'il utilise Define_Method. Je vais soumettre ma propre réponse ci-dessous demain pour la considération de chacun.
class MyClass < Struct.new(:foo, :bar) end
Le problème avec cette solution est que si vous ajoutez un initialiseur avec des arguments, il essuie l'initialiseur de structure par défaut.
Vous pouvez toujours faire des choses comme: classe myClass
J'aime la classe myclass
J'ai constaté que héritating de struct.new () brise () la rechargement automatique des rails et conduit également à TypeErrors: Stackoverflow.com/Questtions/9785694/...
Ce module permet à un hasch comme une option de nouvelle (). Vous pouvez inclure le module dans une classe avec héritage et le constructeur fonctionne toujours.
J'aime mieux que la liste des valeurs d'attr tant que paramètres, car, en particulier avec des attractions héritées, je n'aimerais pas d'essayer de vous rappeler quel paramètre était lequel. p> et vous pouvez faire ceci: p>
Je sais que c'est une vieille question avec des réponses parfaitement acceptables, mais je voulais poster ma solution car il tire parti de Module # Prepend code> (Nouveau dans Ruby 2.2) et le fait que les modules sont aussi des cours Pour une solution très simple. D'abord le module pour faire la magie:
class MyClass
prepend InitializeWith.new :foo, :bar
def initialize extra
puts extra
end
end
MyClass.new 'baz', 'boo', 'dog'
C'est vraiment vague. Quelle partie de cela voulez-vous abstrait? Comment voulez-vous résumer?
De plus, vous pouvez essayer de demander ici: refactoryCode.com
Je souhaite soit créer un module que je peux mélanger en classes ou remplacer la classe elle-même afin que je puisse écrire une seule ligne de code et avoir créé les accesseurs et l'initialisateur.
Avez-vous besoin de spécifier des paramètres non-attr_accessor pour initialiser? Envisagez-vous des commandes générationnelles des attraisons de super-classes dans la signature?
Je ne suis pas sûr ... J'aimerais éviter de perdre l'initialisateur créé par Initialize_with Si un nouvel initialiseur est créé, mais je comprends que cela introduit une certaine confusion autour de la signature de la méthode. Peut-être que vous feriez: foo.new (new_arg, new_arg2,: foo => 1,: bar => 2)? Cela semble également potentiellement déroutant. Les pensées?
Je voudrais probablement aller avec foo.new {user_param ,: user_option => option_value ,: attrs => {: foo => 1,: bar => 2}}. C'est un peu verbeux, mais je ne sais pas comment le faire d'autre. Vous pouvez même classer_eval les Attr_Accessors en provenance d'une initialisation des appelants, s'ils n'existent pas encore sur l'objet.