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

时间:2019-01-21 19:17:40

标签: ruby instance-variables

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

3 个答案:

答案 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返回nili.instance_variables.include(:@ivar)是我能想到的唯一确定@ivar是否已定义的方法,可能等于nil