【问题标题】:Fooling Ruby's case operator, ===, with proxy objects用代理对象欺骗 Ruby 的 case 运算符 ===
【发布时间】:2011-04-01 11:37:46
【问题描述】:

我正在尝试创建一个代理对象,它将几乎所有的方法调用都转移到一个子对象,本质上是委托人模式。在大多数情况下,我只是使用 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#=== 只是在施展某种无法避免的魔法吗?

【问题讨论】:

  • 一句警告:如果您可以通过委派is_a?instance_of?kind_of?class 等来实现您的目标而无需将代理伪装成Fixnum,请执行所以!更改这些方法可能会导致您(或使用/维护您的代码的人)直接陷入调试困境。

标签: ruby proxy operators case introspection


【解决方案1】:

是的,是的。 Module#=== 在 C 中实现,直接检查对象的类层次结构。好像没有办法骗它。

【讨论】:

  • 谢谢。这会带来什么无聊。
【解决方案2】:

问题在于它确实是Fixnum === x,这意味着=== 方法是在Fixnum 上调用的,而不是在x 上调用的。您可以替换现有的所有 === 方法,(并注意何时引入新的 === 方法),但这将是很多工作,而且非常脆弱。

【讨论】:

    【解决方案3】:

    我认为您正在寻找的是 Delegator 类。

    您的 Proxy 类应该继承 Delegator 类,然后定义 __getobj____setobj__ 以获取和设置目标对象。

    算了,我自己试过了,还是不行。

    编辑:

    正如 grddev 提到的,技术问题是 Fixnum 被发送 :=== 方法。然而,进一步考虑,我认为 Ruby 当前的行为是正确的。由于 Delegator 应该是一个隐藏实现细节的抽象接口,因此 Proxy 的实例没有正确地标识为 kind_of?固定编号。

    如果您确实希望 Proxy 类成为 Fixnum 的一种,但希望用方法来装饰它,那么合乎逻辑的做法是继承 Fixnum,或者创建一个 ProxyMethods 模块并扩展 Fixnum 的各个实例。

    当然,由于您不能真正使用 Fixnum.new,因此您必须将 Fixnum 子类化才能扩展单个实例,但一般规则是成立的。

    【讨论】:

    • 只有当您假设程序员无法使用某种形式的对象自省时,技术行为才是正确的,这似乎在 C 中存在。不幸的是,此代理需要跟踪任何类型对象,而不仅仅是 Fixnums,所以扩展确实没有帮助(并且由于各种原因,扩展 Object 也没有用)。
    • 嗯,我明白你的意思了。您希望 :=== 被实现为 send :instance_of?, MyClass 到您的代理对象,但实际上并非如此。我仍然坚持认为,如果您试图伪装成一个对象,但想要某种元功能,那么创建一个装饰和跟踪单个对象的 Tracking 类是一个更好的设计。非单例对象可以扩展,单例实例(例如 Fixnum 和 Symbol)可以被包装和扩展,或者特殊处理。
    【解决方案4】:

    您可能应该搜索一下 BlankSlate 班级。这个类从一个普通的对象中去掉了大部分方法,并且网站有一个简单的代理类的例子,它将打印出所有被调用的方法。这应该让您更好地了解正在发生的事情。对不起,我不能给你更全面的答案,但我在打电话。希望有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-27
      • 1970-01-01
      • 2015-12-31
      相关资源
      最近更新 更多