想象一下,您經常需要從某個靜態代碼或方面內的超類中包裝一組方法,但每個方法的結果/例如,圍繞數組方法更新通知以獲取可觀察數組。Ruby塊 - 包裝和自定義超類方法(使用define_method和塊)
我首先想到的,我要像使用一類級別的方法:
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現在?我最有希望的方法達到了這個目標。
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
錯誤::
如果直接在陣列的子類定義: 超級稱爲如果一個模塊中定義和包括以陣列方法
以外不因爲超級的工作: 「不支持從單一方法定義到多個類的超級方法;如果方法具有適當的返回值,這將在1.9.3或更高版本中修復」或「分段錯誤」)
我搜索了一段時間,但沒有找到一個明智的解決方案來改變閉包的綁定,但是,也許我錯過了什麼,或者你可以解決它沒有?
Rails通過評估字符串來完成這些事情,但還不確定如果我想這樣。性能不是很重要,但會是。因此,我需要關於不同可能性和性能問題的反饋。
最後,我得到了兩個更詳細的解決方案運行。首先,通過實例,沒有超級而自:
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來維護?
有趣的做法,事實上,它再次超級工作,非常感謝! – Micha