hash[key] 是 hash.fetch(key) 就像 @ivar 是什么?

hash[key] is to hash.fetch(key) as @ivar is to what?

扩展标题:如果实例变量尚未初始化,如何以导致异常的方式访问实例变量 (@ivar)?

如果您的意思是 h[k]h.fetch(k) 的简单形式,那么通过模拟:

@ivar
instance_variable_get(:@ivar)

instance_variable_get 方法提供对实例变量的任意访问。

这里的区别是 h[k] 调用 Hash#[] 如果没有找到密钥 returns nil,而 h.fetch(k) 调用 Hash#fetch并且 如果找不到密钥则引发异常 。这种差异非常重要,需要在此处注明。

然而,没有提供与实例变量有关的此功能的内置方法;

由于 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

要做到这一点,我相信您需要从 class 通过 getter 访问实例变量的值。 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 

(public) getter 方法 ivar 如果不需要,可以删除。

@ivar 将return nil 无论是否未定义或已初始化为 nil。同样,如果实例变量没有被定义或者nil是它的当前值,则Object#instance_variable_get returns nili.instance_variables.include(:@ivar) 是我能想到的唯一方法来确定 @ivar 是否已被定义,可能等于 nil