Accessing Ruby Class Variables with class_eval and instance_eval

前端 未结 4 1415
[愿得一人]
[愿得一人] 2021-01-31 04:39

I have the following:

class Test
    @@a = 10

    def show_a()
        puts \"a: #{@@a}\"
    end

    class << self
      @@b = \'40\'

      def show_b
         


        
4条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-31 05:18

    EDIT: below code was tested with 1.8.7 and 1.9.1...it seems the situation is different again with 1.9.2 :/

    The situation actually isn't that straight forward. There are differences in behaviour depending on whether you're using 1.8 or 1.9 and whether you're using class_eval or instance_eval.

    The examples below detail the behaviour in most situations.

    I also included the behaviour of constants, for good measure, as their behaviour is similar to, but not exactly the same as, class variables.

    Class variables

    class_eval in Ruby 1.8:

    class Hello
        @@foo = :foo
    end
    
    Hello.class_eval { @@foo } #=> uninitialized class variable
    

    class_eval in Ruby 1.9:

    Hello.class_eval { @@foo } #=> :foo
    

    So class variables are looked up in 1.9 (but not in 1.8) when using class_eval

    instance_eval in Ruby 1.8 and 1.9

    Hello.instance_eval { @@foo } #=> uninitialized class variable
    Hello.new.instance_eval { @@foo } #=> uninitialized class variable
    

    It appears class variables are not looked up in 1.8 or 1.9 when using instance_eval

    What is also interesting is the case for constants:

    Constants

    class_eval in Ruby 1.8

    class Hello
        Foo = :foo
    end
    
    Hello.class_eval { Foo } #=> uninitialized constant
    

    class_eval in Ruby 1.9

    Hello.class_eval { Foo } #=> :foo
    

    So, as with class variables, constants are looked up in 1.9 but not in 1.8 for class_eval

    instance_eval in Ruby 1.8

    Hello.instance_eval { Foo } #=> uninitialized constant
    Hello.new.instance_eval { Foo } #=> uninitialized constant
    

    instance_eval in Ruby 1.9

    Hello.instance_eval { Foo } #=> uninitialized constant
    Hello.new.instance_eval { Foo } #=> :foo
    

    It appears that constant lookup is not quite analogous to class variable look up for Ruby 1.9. A Hello instance does get access to the constant while the Hello class does not.

提交回复
热议问题