具有attr\u访问器的类上的Ruby实例\u eval
我理解具有attr\u访问器的类上的Ruby实例\u eval,ruby,attr-accessor,class-eval,instance-eval,Ruby,Attr Accessor,Class Eval,Instance Eval,我理解实例评估和类评估之间的基本区别。不过,我在玩游戏时发现了一些奇怪的事情,涉及到attr\u访问器。下面是一个例子: A = Class.new A.class_eval{ attr_accessor :x } a = A.new a.x = "x" a.x => "x" # ... expected A.instance_eval{ attr_accessor :y } A.y = "y" => NoMethodError: undefined method `y='
实例评估
和类评估
之间的基本区别。不过,我在玩游戏时发现了一些奇怪的事情,涉及到attr\u访问器
。下面是一个例子:
A = Class.new
A.class_eval{ attr_accessor :x }
a = A.new
a.x = "x"
a.x
=> "x" # ... expected
A.instance_eval{ attr_accessor :y }
A.y = "y"
=> NoMethodError: undefined method `y=' for A:Class
a.y = "y"
=> "y" # WHATTT?
这是怎么回事:
方法
attr\u accessor
是一种类方法,当在类的主体中调用时,访问器方法在该类的实例上定义
当您执行A.class\u eval{…}
时,您在类A
的主体中调用它,因此它的实例如A
被分配了访问器
当您执行A.instance\u eval{…}
时,您在类的非主体中调用它,因此它的实例不被分配访问器
如果您执行
Class.Class_eval{attr\u accessor:z}
,那么您将使用类的主体调用它,因此,它的实例如A
将被分配访问器:A.z=…
有关类评估
和实例评估
之间的差异,请参阅
正如您在B中所看到的,尽管实例求值通常创建单例方法,但显然
attr\u accessor
和define\u method
强制定义实例方法。首先,您的理解(或直觉)是正确的,在#instance_eval
和#class_eval
中定义的方法不同
A = Class.new
A.instance_eval { def defined_in_instance_eval; :instance_eval; end }
A.class_eval { def defined_in_class_eval; :class_eval; end }
A.new.defined_in_class_eval # => :class_eval
A.defined_in_instance_eval # => :instance_eval
旁注:虽然self
在instance\u eval
和class\u eval
中都是相同的,但是默认定义者不同,请参见
真正的诀窍是模块#attr_访问器
本身,看看它的定义:
它不使用
def
,不读取上下文、self
或默认定义者。它只是“手动”将方法插入到模块中。这就是结果违反直觉的原因。伙计,这太糟糕了。很好的例子@Daniel_Vartanov的回答实际上解释了为什么attr_accessor
不适用于self,但这是一个很好的方法,可以准确地说明每种类型的方法def'n会发生什么。非常感谢。
A.singleton_class.class_eval { attr_accessor :y }
A.y = 'y'
A.y
A = Class.new
A.instance_eval { def defined_in_instance_eval; :instance_eval; end }
A.class_eval { def defined_in_class_eval; :class_eval; end }
A.new.defined_in_class_eval # => :class_eval
A.defined_in_instance_eval # => :instance_eval
A.singleton_class.class_eval { attr_accessor :y }
A.y = 'y'
A.y