在标题上展开:如果未初始化实例变量,如何以导致异常的方式访问实例变量(@ivar
)?
答案 0 :(得分:5)
但是,没有内置的方法可以针对实例变量提供此功能;
由于在您的示例中Hash#[]
类似于@ivar
(或instance_variable_get(:@ivar)
),因此Hash#fetch
类似于
def instance_variable_fetch(sym)
raise(NameError, "instance variable not found: #{sym}") unless instance_variable_defined?(sym)
instance_variable_get(sym)
end
示例:
@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
答案 1 :(得分:1)
如果您的意思是h[k]
是h.fetch(k)
的简单形式,那么可以通过模拟:
@ivar
instance_variable_get(:@ivar)
instance_variable_get
方法提供对实例变量的任意访问。
这里的区别是h[k]
调用Hash#[]
,如果找不到密钥,则返回nil
,而h.fetch(k)
调用Hash#fetch
并提高如果找不到密钥,则为例外。这种区别足够重要,需要在这里注意。
答案 2 :(得分:1)
要做到这一点,我相信您将需要从类中通过专用的getter访问实例变量的值。吸气剂可以设为私有。
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
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
(公共)getter方法ivar
可能会被删除(如果不需要的话)。
@ivar
将返回nil
,无论它是否尚未定义或已初始化为nil
。同样,如果尚未定义实例变量或nil
是其当前值,则Object#instance_variable_get返回nil
。 i.instance_variables.include(:@ivar)
是我能想到的唯一确定@ivar
是否已定义的方法,可能等于nil
。