代码之家  ›  专栏  ›  技术社区  ›  AlbertMunichMar

为什么在创建后看不到实例变量?(属性读取器)

  •  0
  • AlbertMunichMar  · 技术社区  · 6 年前

    我有以下代码,动态创建实例变量。如果实例变量不存在,则使用no method错误创建 attr_reader attr_writer 方法是动态的。一切正常,但我不明白为什么我看不到 @anything 在创建第一个 磨光机 .

    require "pry-byebug"
    
    class UberHash
      attr_accessor :color
      def initialize
        @color = nil
      end
    
      def method_missing(m, *args, &block)
        if m.match(/=/)
          puts "create attr writer"
          self.instance_variable_set("@#{m[0..-2]}", args[0])
        else
          puts "create attr reader"
          self.instance_variable_get("@#{m}")
        end
      end
    end
    
    uber_hash = UberHash.new
    puts "call 1 .................."
    p "uber_hash.anything: #{uber_hash.anything}"
    p "uber_hash.inspect: #{uber_hash.inspect}"
    p uber_hash.anything = "hola"
    p uber_hash.inspect
    

    结果如下:

    call 1 ..................
    create attr reader
    "uber_hash.anything: "
    "uber_hash.inspect: #<UberHash:0x00007f851b1e41a8 @color=nil>"
    "#<UberHash:0x00007f851b1e41a8 @color=nil>"
    create attr writer
    "hola"
    "#<UberHash:0x00007f851b1e41a8 @color=nil, @anything=\"hola\">"
    

    在创建第一个实例变量之后 anything ,使用instnace_variable_set方法,我知道我创建了一个attr_reader,对吗?

    为什么我看不到 @任何东西 实例变量如果我检查实例?

    2 回复  |  直到 6 年前
        1
  •  0
  •   maicher    6 年前

    在第一次检查中看不到实例变量。你希望它在那里,因为在前一行你打电话给 uber_hash.anything 对吧?

    嗯, 什么都行 调用计算 else #method_missing 有条件的: self.instance_variable_get("@#{m}") -这就是为什么没有设置实例变量。

    此外,在 #缺少方法 条件打印两条消息: puts "create attr writer" puts "create attr reader" -他们错了。应该是: puts "create instance variable" puts "read instance variable"

        2
  •  0
  •   Masa Sakano    6 年前

    在创建第一个实例变量anything之后,使用 instnace_variable_set ,我知道我创建了一个attr_reader,对吗?

    不,那是不对的。你的类从不创建(或运行) attr_reader . 试试这个(在运行示例命令之后)

    p( uber_hash.methods - Object.new.methods )
    

    你只看到在你的类中额外定义的方法 [:color, :color=, :method_missing] 在你们班上。

    方法 :color 是因为 attr_accessor :color . 记得 attr_accessor etc只是定义方法的捷径。 相比之下,这种方法 :anything 定义,因为您的类从未定义该方法。 相反,在你的课堂上,每次 uber_hash.anything 被称为 uber_hash.method_missing 运行并执行作业,即操作或查看实例变量 @anything .

    第二,同时 instance_variable_set 为实例变量设置值(如果不存在则创建它)。 instance_variable_get 仅当它存在时才引用它,否则返回nil并执行 创建实例变量。这就是为什么 任何东西 创建于 实例变量集 ,但不只是在 实例变量获取 . 试试这个(在定义了类之后)来看看要点。

    class UberHash
      def test_pr
        print 'color='; p instance_variable_get("@color")
        print 'other='; p instance_variable_get("@other")
        p instance_variables  # => @other is not defined
        print 'other='; p instance_variable_set("@other", 99)
        p instance_variables  # => @other is NOW defined
      end
    end
    
    uber_hash.test_pr
    

    因此,你看到的行为是完全合法的。

    注: this past answer 解释一下。