gpt4 book ai didi

Ruby block - 包装和自定义父类(super class)方法(使用 define_method 和 block )

转载 作者:数据小太阳 更新时间:2023-10-29 08:05:23 26 4
gpt4 key购买 nike

想象一下,您经常需要将来自父类(super class)的一组方法包装在一些静态代码或外观中,但每个方法只有几行结果/不同,例如,将更新通知包装在数组方法周围以获得可观察数组。

我的第一个想法是,我想要一个类级别的方法,如下所示:

class MyArray < Array
extend ObserverHelper # defines :wrap_method

wrap_notify(:[]=) do |index_or_range, *args|
[self[index_or_range], super(index_or_range, *args)]
# much nicer it would be to define
# removed = self[index_or_range]
# added = super(index_or_range, *args)
# but this makes it even more complicated (suggestions welcome!)
end
...
end

到目前为止一切顺利。现在如何实现 :wrap_method ?我最有希望的方法做到了这一点。不工作,因为 super :

require 'observer'

module ObserverHelper
include Observable

def wrap_notify(meth, &block)
define_method meth,->(*args) {
removed, added = instance_exec(*args, &block)
changed
notify_observers(removed, added)
added
}
end
end

错误:

  • 如果直接在数组子类上定义:super 在方法外调用

  • 如果在模块中定义并包含在数组中:“不支持定义为多个类的单例方法的 super;这将在 1.9.3 或更高版本中修复”或“段错误”(如果该方法具有正确的返回值)

我搜索了一段时间,但没有找到更改闭包绑定(bind)的可取解决方案,但是,也许我遗漏了什么,或者您可以在没有的情况下解决它?

Rails 通过评估字符串来完成这些事情,但不确定我是否愿意这样做。性能目前还不重要,但会很重要。因此,我需要有关不同可能性和性能问题的反馈。

最后,我运行了两个更详细的解决方案。首先,传递实例,没有 super 也没有 self:

  wrap_observer(:[]=) do |instance, index_or_range, *args|
[instance[index_or_range], instance.send(meth, index_or_range, *args)]
end

另一个使用 wrap_observer 作为 instance_method:

  def []=(index_or_range, *args)
wrap_observer do
[self[index_or_range], super(index_or_range, *args)]
end
end

我认为这是更可取的。

DSL 的一个解决方案可能是在没有包装器的情况下定义方法,而不是通过添加包装器的已定义方法进行迭代。

是否有更多方法可以解决我预期的 DSL 的性能和可维护性问题?

最佳答案

重新绑定(bind) block 的唯一方法是用它定义一个方法,这也允许使用 super。因此,您需要定义两种方法——可以使用模块完成的方法:

module ObserverHelper
def wrap_notify(meth, options={}, &block)
override = Module.new do
define_method(meth, &block)
end
notifier = Module.new do
define_method meth do |*args|
removed, added = super(*args)
options ||= {}
changed
notify_observers(removed, added)
after
end
end
include override
include notifier
end
end

关于Ruby block - 包装和自定义父类(super class)方法(使用 define_method 和 block ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10674966/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com