Search code examples
rubyclass-eval

Class eval passing the class varibale by reference


The following code snippet:

class A
end
    @class = eval("A")
    @class.class_eval do
        @@attr = 100
        def self.get_attr
            @@attr
        end
        def self.set_attr(_x)
            @@attr = _x
        end
    end

    class B
    end

    @class = eval("B")
    @class.class_eval do
        @@attr = 100
        def self.get_attr
            @@attr
        end
        def self.set_attr(_x)
            @@attr = _x
        end
    end
    a = A.new
    b = B.new
    A.set_attr(103)
    B.set_attr(222)
    puts A.get_attr
    puts B.get_attr

Class variable is getting shared.

Result:

222 222


Solution

  • It's because you set not the variable you think you do.

    class A; end
    
    @class = eval("A")
    @class.class_eval do
      class_variable_set :@@attr, 100
    
      def self.get_attr
        class_variable_get :@@attr
      end
    
      def self.set_attr(_x)
        class_variable_set :@@attr, _x
      end
    end
    
    class B
    end
    
    @class = eval("B")
    @class.class_eval do
      class_variable_set :@@attr, 100
    
      def self.get_attr
        class_variable_get :@@attr
      end
      def self.set_attr(_x)
        class_variable_set :@@attr, _x
      end
    end
    
    A.set_attr(103)
    B.set_attr(222)
    puts A.get_attr
    puts B.get_attr
    
    # >> 103
    # >> 222
    

    When I run your code, it gives several warnings of "Access to class variable from toplevel". So, apparently, you're setting and reading class variables of main object, not of your classes.