使用代理对象欺骗 Ruby 的大小写运算符 ===

发布于 2024-09-15 09:15:13 字数 581 浏览 3 评论 0原文

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

I'm trying to make a proxy object that transfers almost all method calls to a child object, essentially the delegator pattern. For the most part, I'm just using a BasicObject and passing every call with method_missing to the child object. So far, so good.

The trick is that try as I might, I can't fool Ruby's case operator, so I can't do:

x = Proxy.new(15)
Fixnum === x #=> false, no matter what I do

This of course makes any case x operations fail, which means the proxies can't be handed off safely to other libraries.

I can't for the life of me figure out what === is using. The proxy works fine for all of the class-based introspection I know of, which is all correctly passed to the child object:

x.is_a?(Fixnum) #=> true
x.instance_of?(Fixnum) #=> true
x.kind_of?(Fixnum) #=> true
x.class #=> Fixnum

Is Module#=== just doing some kind of magic that can't be avoided?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

违心° 2024-09-22 09:15:13

是的,确实如此。 Module#=== 用 C 实现,直接检查对象的类层次结构。看起来没有办法欺骗它。

Yeah, it is. Module#=== is implemented in C, examining the object's class hierarchy directly. It doesn't look like there's a way to fool it.

两仪 2024-09-22 09:15:13

问题是它执行了 Fixnum === x,这意味着 === 方法是在 Fixnum 上调用的,而不是在 >x。您可以替换现有的所有 === 方法(并且还要注意何时引入新的 === 方法),但这将是大量工作,并且相当脆弱。

The problem is that it does Fixnum === x, which means that the method === is called on Fixnum and not on x. You could replace all === methods in existence, (and also watch for when new === methods are introduced), but that would be a lot of work, and quite fragile.

守护在此方 2024-09-22 09:15:13

<罢工>
我认为您正在寻找的是 Delegatorclass.

您的 Proxy 类应该是 Delegator 类的子类,然后定义 __getobj____setobj__ 来获取和设置目标对象。

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

编辑:

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

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

当然,由于您无法真正执行 Fixnum.new,因此您必须子类化 Fixnum 才能扩展单个实例,但一般规则仍然有效。


I think what you're looking for is the Delegator class.

Your Proxy class should subclass the Delegator class, then define __getobj__ and __setobj__ to get and set the target object.

Forget that, I tried it myself and it doesn't work.

EDIT:

As grddev mentions, the technical issue is that Fixnum is being sent the :=== method. Thinking about it further, however, I think Ruby's current behavior is correct. Since a Delegator is supposed to be an abstract interface to hide implementation details, instances of Proxy are correctly not identified as a kind_of? Fixnum.

If you really want the Proxy class to be a kind of Fixnum but wish to decorate it with methods, the logical thing to do is to either subclass Fixnum, or create a ProxyMethods module and extend individual instances of Fixnum.

Of course, since you can't really do Fixnum.new, you'll have to subclass Fixnum in order to extend a single instance, but the general rule stands.

猫腻 2024-09-22 09:15:13

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

you should probably do a search for the BlankSlate
class. This class strips out most of the methods from a normal Object and the website has an example of a simple Proxy class that will print out all methods being called. This shoul give you a better picture of what is happening. Sorry I can't give you a fuller answer but I'm on my phone. Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文