我正在尝试创建一个代理对象,它几乎将所有方法调用都传递给子对象,实际上是委托者模式。在大多数情况下,我只是使用BasicObject并将每个使用method_missing的调用传递给子对象。到目前为止,非常好。
诀窍是尽我所能,我不能欺骗Ruby的case操作符,所以我不能这样做:
x = Proxy.new(15)
Fixnum === x #=> false, no matter what I do
这当然会导致任何case x
操作失败,这意味着代理无法安全地传递给其他库。
我不能为我的生活找出===正在使用的东西。代理适用于我所知道的所有基于类的内省,它都正确地传递给子对象:
x.is_a?(Fixnum) #=> true
x.instance_of?(Fixnum) #=> true
x.kind_of?(Fixnum) #=> true
x.class #=> Fixnum
Module#===
只是在做某种无法避免的魔法吗?
答案 0 :(得分:1)
Module#===
在C中实现,直接检查对象的类层次结构。看起来没有办法愚弄它。
答案 1 :(得分:0)
<击>
我认为你要找的是Delegator
类。
你的Proxy类应该是Delegator类的子类,然后定义__getobj__
和__setobj__
来获取和设置目标对象。
击>
忘记这一点,我自己尝试了它并没有用。
编辑:
正如grddev所提到的,技术问题是Fixnum正在发送:===方法。然而,考虑到它,我认为Ruby目前的行为是正确的。由于Delegator应该是隐藏实现细节的抽象接口,因此Proxy的实例没有被正确识别为kind_of? Fixnum对象。
如果你真的希望Proxy类是一种Fixnum但希望用方法来装饰它,那么逻辑上要做的是子类Fixnum,或者创建一个ProxyMethods模块并扩展Fixnum的各个实例。
当然,既然你不能真正做Fixnum.new,你必须继承Fixnum才能扩展单个实例,但一般规则就是这样。
答案 2 :(得分:0)
问题在于它Fixnum === x
,这意味着方法===
在Fixnum
而非x
上调用。您可以替换现有的所有===
方法(并且还会注意何时引入新的===
方法),但这将是一项很多工作,并且非常脆弱。
答案 3 :(得分:0)
你应该搜索BlankSlate 类。此类从普通对象中删除大多数方法,并且网站有一个简单的Proxy类的示例,它将打印出所有被调用的方法。这可以让你更好地了解正在发生的事情。对不起,我不能给你一个更全面的答案,但我在打电话。希望有所帮助。