0

以下代码片段:

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

类变量正在共享。

结果:

222 222

4

3 回答 3

1

这是因为你没有设置你认为你做的变量。

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

当我运行您的代码时,它会给出几个“从顶层访问类变量”的警告。因此,显然,您正在设置和读取main对象的类变量,而不是您的类。

于 2013-04-02T10:26:23.167 回答
0

看下面的代码:

class A
end
@class = eval("A")
@class.class_eval do
    @@attr = 100
    def self.get_attr
        @@attr
    end
    def self.set_attr(_x)
        p "hi"
        @@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)
        p "hi"
        @@attr = _x
    end
end
a = A.new
b = B.new
A.set_attr(103)
B.set_attr(222)

p A.class_variable_defined?(:@@attr) 
p B.class_variable_defined?(:@@attr) 
p Object.class_variable_defined?(:@@attr)

p A.class_variable_get(:@@attr)
p B.class_variable_get(:@@attr)
p Object.class_variable_get(:@@attr)

p A.class_variables
p B.class_variables
Object.remove_class_variable(:@@attr)
p A.class_variables
p B.class_variables

输出:

true
true
true
222
222
222
[:@@attr]
[:@@attr]
[]
[]

说明:根据您的代码@@attr属于Object类类变量。并且根据RubyA 和 B 都是Object. 因此类变量@@attr已被共享。

Module#class_eval说:

(a) 这可用于向类添加方法。

(b) 当给定一个块时,常量/类变量查找不受影响。

这是 ruby​​ 的特性,如果你class variable在里面使用class_eval它会class variable在类中搜索Object

为了使其可见,我编写了以下代码,这反过来将证明:常量/类变量查找不受影响。

@@avar = 1
class A < BasicObject
@@avar = "hello"
end
A.class_eval { puts @@avar }

查看代码输出:

D:/Rubyscript/My ruby learning days/Scripts/TEST.RB:91: warning: class variable
access from toplevel
D:/Rubyscript/My ruby learning days/Scripts/TEST.RB:95: warning: class variable
access from toplevel
1
于 2013-04-02T10:36:51.270 回答
0

检查下面的代码,

class A
end

class B
end

ADD_ATTR = lambda do
    @@attr = 100
    def self.get_attr
      puts "self : #{self} getting attr : #{@@attr}"
        @@attr
    end
    def self.set_attr(_x)
      puts "self : #{self} setting attr : #{@@attr} to _x : #{_x}"
        @@attr = _x
    end
end

A.class_eval &ADD_ATTR
B.class_eval &ADD_ATTR

a = A.new
b = B.new

A.set_attr(103)
B.set_attr(222)
puts A.get_attr
puts B.get_attr


ADD_BTTR = '
    @@bttr = 100
    def self.get_bttr
      puts "self : #{self} getting bttr : #{@@bttr}"
        @@bttr
    end
    def self.set_bttr(_x)
      puts "self : #{self} setting bttr : #{@@bttr} to _x : #{_x}"
        @@bttr = _x
    end
'
A.class_eval ADD_BTTR
B.class_eval ADD_BTTR

A.set_bttr(103)
B.set_bttr(222)
puts A.get_bttr
puts B.get_bttr

似乎ruby在将对象方法加入类之前在对象方法的上下文中进行块评估,因此评估发生在代码附加到类之前,它需要将属性附加到对象方法,以证明我使用的点带有 lambda 运算符的代码。

同时,如果我们使用字符串执行类 eval,则相同的代码可以工作

这是我得到的输出:

self : A 设置 attr : 100 to _x : 103
self : B 设置 attr : 103 到 _x : 222
self : 获取 attr : 222
222
自我:B 获得属性:222
222
self : 一个设置 bttr : 100 到 _x : 103
self : B 设置 bttr : 100 到 _x : 222
self : 越来越 bttr : 103
103
自我:B得到bttr:222
222
于 2013-04-02T11:12:22.637 回答