- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我有一个类,我在运行时动态地向其添加属性访问器。此类构成 DSL 的一部分, block 由此传递给配置方法并使用 instance_eval 调用。这使得在引用类的方法时可以在 DSL 中删除对“self”的引用。
但是,我发现我可以引用属性来检索它们的值,但无法分配它们,除非明确引用自身,如以下代码示例所示。
class Bar
def add_dynamic_attribute_to_class(name)
Bar.add_dynamic_attribute(name)
end
def invoke_block(&block)
instance_eval &block
end
def self.add_dynamic_attribute(name)
attr_accessor name
end
end
b = Bar.new
b.add_dynamic_attribute_to_class 'dyn_attr'
b.dyn_attr = 'Hello World!'
# dyn_attr behaves like a local variable in this case
b.invoke_block do
dyn_attr = 'Goodbye!'
end
# unchanged!
puts "#{b.dyn_attr} but should be 'Goodbye!'"
# works if explicitly reference self
b.invoke_block do
self.dyn_attr = 'Goodbye!'
end
# changed...
puts "#{b.dyn_attr} = 'Goodbye!"
# using send works
b.invoke_block do
send 'dyn_attr=', 'Hello Again'
end
# changed...
puts "#{b.dyn_attr} = 'Hello Again!"
# explain this... local variable or instance method?
b.invoke_block do
puts "Retrieving... '#{dyn_attr}'"
# doesn't fail... but no effect
dyn_attr = 'Cheers'
end
# unchanged
puts "#{b.dyn_attr} should be 'Cheers'"
谁能解释为什么这不符合预期?
最佳答案
问题出在 Ruby 处理实例变量和局部变量的方式上。发生的情况是您在 instance_eval block 中设置了一个局部变量,而不是使用 ruby 访问器。
这可能有助于解释:
class Foo
attr_accessor :bar
def input_local
bar = "local"
[bar, self.bar, @bar, bar()]
end
def input_instance
self.bar = "instance"
[bar, self.bar, @bar, bar()]
end
def input_both
bar = "local"
self.bar = "instance"
[bar, self.bar, @bar, bar()]
end
end
foo = Foo.new
foo.input_local #["local", nil, nil, nil]
foo.input_instance #["instance", "instance", "instance", "instance"]
foo.input_both #["local", "instance", "instance", "instance"]
bocks 的工作方式是它们区分局部变量和实例变量,但是如果在调用读取器时未定义局部变量,则该类默认为实例变量(就像我在调用 input_instance 时的情况一样)示例)。
可通过三种方式获得所需的行为。
使用实例变量:
class Foo attr_accessor :bar def evaluate(&block) instance_eval &block end end foo = Foo.new foo.evaluate do @bar = "instance" end foo.bar #"instance"
使用自变量:
class Foo attr_accessor :bar def evaluate(&block) block.call(self) end end foo = Foo.new foo.evaluate do |c| c.bar = "instance" end foo.bar #"instance"
使用setter函数:
class Foo attr_reader :bar def set_bar value @bar = value end def evaluate(&block) instance_eval &block end end foo = Foo.new foo.evaluate do set_bar "instance" end foo.bar #"instance"
所有这些示例都将 foo.bar 设置为“instance”。
关于ruby - 在 Ruby 中通过 instance_eval 调用 block 时,动态添加的访问器分配不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4403973/
我有以下代码: class A def self.scope yield end def self.method_added method self.instance_ev
我对 instance_eval 的理解是,如果我有模块 M,那么以下是等价的: module M def foo :foo end end class C class true
单例方法是一种只在一个实例上定义的方法。 foo = Foo.new def foo.case #singleton method end instance_eval 不是做同样的事情吗?为特定实
我正在尝试一些 ruby 元编程,但对 instance_eval() 感到有些困惑。 看下面的例子 @instance_var = 'instance_var' local_var = 'loc
虽然我已经使用了一段时间,但我似乎对这两种方法感到困惑,我无法理解为什么方法 passengers 没有被添加到以下代码中的对象中: class Bus def number_of_seats
看着这个instance_eval示例: class KlassWithSecret def initialize @secret = 99 end def g
我正在尝试调用对象 foo 的方法,就好像它是对象 bar 的方法一样。我尝试了两种方法: 1。解除绑定(bind)和绑定(bind) - 由于类不同而失败 class Foo def initi
当我在 instance_eval block 中为类定义一个方法时,它会创建一个很好的类方法。 例如) class A end A.instance_eval do def method; en
我想对 DSL 进行一些改进。我能够使用此示例进行改进: module ArrayExtras refine Array do def speak puts 'array!'
Foo = Class.new Foo.instance_eval do def instance_bar "instance_bar" end end puts Foo.instan
class_eval 有什么区别吗? & instance_eval工作除了def ?里面class_eval block def定义类自身的方法(即实例方法)和内部 instance_eval de
我发现传递给 class_eval、module_eval 和 instance_eval 的行号与错误报告的行号不匹配。 ruby-doc 未解释此行为其中说:(以 instance_eval 为例
伙计们。我创建了一个类: class A def initialize &b instance_eval &b end def method_missing method_id,
完整代码:http://friendpaste.com/5TdtGPZaEK0DbDBa2DCUyB class Options def method_missing(method, *arg
我正在研究 Pickaxe 1.9,我对 instance/class_eval block 中的常量查找感到有点困惑。我正在使用 1.9.2。 似乎 Ruby 在 *_eval block 中处理常
我了解 instance_eval 和 class_eval 之间的基本区别。我在玩弄时发现的是一些涉及 attr_accessor 的奇怪东西。这是一个例子: A = Class.new A.cla
class Foo include Module.new { class_eval "def lab; puts 'm' end" } def lab super
我知道 send 接受带有参数的字符串或符号,而 instance_eval 接受字符串或 block ,并且它们的区别在给定接收者时可能很明显。 我的问题是下面示例的“幕后”区别是什么? 1234.
如果我这样做 def eval_file(file) instance_eval read(file) end 然后,一旦文件内的方法/ block 之一发生某些事情,我所看到的就是“eval_f
我最近尝试做类似的事情: a = "some string" b = Proc.new{ upcase } a.instance_eval b 这给出了错误: TypeError: can't con
我是一名优秀的程序员,十分优秀!