J'aimerais quelque chose de similaire à une structure, mais qui utilise des arguments de mots clés à la place: p> < Pré> xxx pré> qui pourrait ressembler à quelque chose comme ceci: p> mais ce qui devrait aller dans les accolades pour définir un struct code> me permet de créer une nouvelle classe qui prend des arguments et a une belle sémantique. Cependant, les arguments ne sont pas obligés et leur commande nécessite de consulter la définition:
initialize code> Méthode sur
Klass code> tel que: p>
attributs code>; et li>
4 Réponses :
Je pourrais mal comprendre la question mais cherchez-vous quelque chose comme ça? ALORS P> Point = StricterStruct.new(:x,:y)
#=> Point
p = Point.new(x: 12, y: 77)
#=> #<Point:0x2a89400 @x=12, @y=77>
p2 = Point.new(x: 17)
#=> ArgumentError
p2 = Point.new(y: 12)
#=> ArgumentError
p2 = Point.new(y:17, x: 22)
#=> #<Point:0x28cf308 @y=17, @x=22>
Ce n'est pas tout à fait raison - comme mon exemple montre, point.new (x: 12) code> aurait dû vous avoir donné une argumentError depuis que vous n'avez pas spécifié
y code>.
@Johnfeminella a raté cette partie. Maintenant, il semble encore plus laid :( mais fonctionne comme demandé.
Je ne comprends pas pourquoi vous introduisez la variable de classe, car attributs code> est visible avec
définir_method code>.
@Johnfeminellellella a nettoyé beaucoup, j'aime mieux votre message d'erreur, mais cela acceptera les chaînes ou les symboles et les convertira en snake_case downcase.
Il me semble que ce serait mieux sans attributs.map! Code>.
@CarySwoveland Je voulais que cela accepte des choses comme stricterstruct.new ("Ceci est un var") Code> the
attributs.map! Code> L'appel me permet de changer cela en place sur
["this_is_a_var"] code>
Oui, je sais, mais cela répond à une question différente. La question est très spécifique sur les attributs, conformément à un resserrement de struct code>. En outre, la méthode d'appel peut ne pas vouloir que ces attributs modifiés.
J'ai chuté en utilisant un (étonnamment pythonique) ** kwargs code> stratégie, grâce aux nouvelles fonctionnalités de Ruby 2.0 +:
module StricterStruct
def self.new(*attribute_names_as_symbols)
c = Class.new
l = attribute_names_as_symbols
c.instance_eval {
define_method(:initialize) do |**kwargs|
unless kwargs.keys.sort == l.sort
extra = kwargs.keys - l
missing = l - kwargs.keys
raise ArgumentError.new <<-MESSAGE
keys do not match expected list:
-- missing keys: #{missing}
-- extra keys: #{extra}
MESSAGE
end
kwargs.map do |k, v|
instance_variable_set "@#{k}", v
end
end
l.each do |sym|
attr_reader sym
end
}
c
end
end
J'aime le message que je viens de changer le mien pour avoir une structure très similaire bien que je vous ai donné des méthodes de getter et de réglage pour l'instance_variables. Désolé, je n'étais pas aussi rapide que vous répondez à votre propre question :). Notez également que j'ai mis à jour ma réponse pour accepter des chaînes ou des symboles et de les formater comme snake_case.
Ne voulez-vous pas dire def self.new (* attribut_names_as_symbols) code>? En outre, je pense que vous pouvez créer chaque accesseur de lecture avec
attr_reader sym code>. Question interessante.
@CarySwoveland Oui, c'est une faute de frappe de ma pâte de copie. Merci d'avoir attrapé ça. Vous avez également raison que Att_Reader est beaucoup plus simple; J'aurais dû ramasser sur ça!
On dirait que vous recherchez: OpenStruct :
require 'ostruct' foo = OpenStruct.new(bar: 1, 'baz' => 2) foo # => #<OpenStruct bar=1, baz=2> foo.bar # => 1 foo[:bar] # => 1 foo.baz # => 2 foo.baz = 3 foo # => #<OpenStruct bar=1, baz=3>
Comme je l'ai mentionné dans l'exemple, l'une des propriétés souhaitées est que argumentError code> ou une exception similaire est soulevé si vous ne spécifiez pas tout. Parce qu'un
openStruct code> peut être modifié à tout moment, ce n'est pas un bon choix ici. De plus, OpenSruct est beaucoup plus lent que la structure, donc si vous en faites beaucoup, c'est cher.
J'ai toujours considéré l'openssatrice comme la classe pour les personnes qui n'étaient pas sûres de ce qu'ils voulaient. Votre cas nécessite une vérification plus rigoureuse une fois que l'instance est créée, ce qui est définitivement où OpenSrUCT échoue et que je pense être un vote en panne pour OpenStruct. Peut-être que votre code serait un bon ajout à Ruby et OpenSruct pourrait être obsolète à cause de sa lenteur.
Je cherchais également cela pour cela, et éventuellement trébuché à travers ce joyau qui fait exactement cela:
https: //github.com/etiennebarrie/kwattr p> au lieu de p>