Pour développer le titre: comment puis-je accéder à une variable d'instance ( @ivar ) d'une manière qui entraîne une exception si la variable d'instance n'a pas été initialisée?
3 Réponses :
Si vous voulez dire que h [k] est la forme simple de h.fetch (k) alors par analogique:
@ivar instance_variable_get(:@ivar)
La méthode instance_variable_get fournit un accès arbitraire aux variables d'instance.
La différence ici est que h [k] appelle Hash # [] qui renvoie nil code> si aucune clé n'est trouvée, tandis que h.fetch (k) appelle Hash # fetch et lève une exception si la clé n'est pas trouvée . Cette différence est suffisamment importante pour être notée ici.
Cependant, aucune méthode intégrée ne fournit cette fonctionnalité en ce qui concerne les variables d'instance;
Puisque Hash # [] est analogue à @ivar (ou instance_variable_get (: @ ivar) ) dans votre exemple, alors Hash # fetch serait analogue à
@var = 42 instance_variable_fetch(:@var) #=> 42 @ivar = nil instance_variable_fetch(:@ivar) #=> nil instance_variable_fetch(:@other_var) #=> NameError: instance variable not found: @other_var
Exemple:
def instance_variable_fetch(sym)
raise(NameError, "instance variable not found: #{sym}") unless instance_variable_defined?(sym)
instance_variable_get(sym)
end
Pour ce faire, je pense que vous auriez besoin d'accéder à la valeur de la variable d'instance, à partir de la classe, via un getter exclusivement. Le getter pourrait être rendu privé.
i = C.new i.instance_variables #=> [] i.ivar #=> RuntimeError (@ivar has not been set) i.instance_variable_get(:@ivar) #=> RuntimeError (@ivar has not been set) i.tell_ivar #=> RuntimeError (@ivar has not been set) i.ivar = 'cat' i.instance_variables #=> [:@ivar] i.ivar #=> "cat" i.instance_variable_get(:@ivar) #=> "cat" i.tell_ivar # cat is the value of @ivar
class C
attr_writer :ivar
alias :o_instance_variable_get :instance_variable_get
def ivar
givar
end
def instance_variable_get(v)
(v==:@ivar || v=="@ivar") ? givar : o_instance_variable_get(v)
end
def tell_ivar
puts "#{givar} is the value of @ivar"
end
private
def givar
raise RuntimeError, "@ivar has not been set" unless
instance_variables.include?(:@ivar)
@ivar
end
end
La méthode de lecture (publique) ivar peut être supprimé s'il n'est pas souhaité.
@ivar renverra nil indépendamment du fait qu'il n'ait pas été défini ou qu'il ait été initialisé à nil . De même, Object # instance_variable_get renvoie nil si la variable d'instance n'a pas été définie ou nil est sa valeur actuelle. i.instance_variables.include (: @ ivar) est le seul moyen auquel je pourrais penser pour déterminer si @ivar a été défini, éventuellement égal à nil code>.