gpt4 book ai didi

ruby - Delegator 通过 BasicObject 透明化

转载 作者:数据小太阳 更新时间:2023-10-29 07:36:39 24 4
gpt4 key购买 nike

上下文:我正尝试在 Ruby 中建立装饰器模式。由于 Decorator 应该将所有未知方法委托(delegate)给底层对象,因此我使用了 Delegator 类。我本可以使用 SimpleDelegator,但我想完全理解我在做什么。

所以我得出的基本代码是:

class Decorator < Delegator
def initialize(component)
super
@component = component
end

def __setobj__(o); @component = o end
def __getobj__; @component end
def send(s, *a); __send__(s, *a) end
end

这与 SimpleDelegator 的实现完全相同。看起来不错。

但我不希望处理装饰器的代码知道它正在操纵装饰器。我想要完全透明。

此时Decorator.new(Object.new).class返回了Decorator

所以我稍微修改了一下,想出了这个:

class Decorator < Delegator
undef_method :==
undef_method :class
undef_method :instance_of?

# Stores the decorated object
def initialize(component)
super
@component = component
end

def __setobj__(o); @component = o end
def __getobj__; @component end
def send(s, *a); __send__(s, *a) end
end

这样,我可以安全地在装饰对象上使用 classinstance_of?,它会通过 method_missing(由 Delegator 实现)将方法发送到底层对象).

问题是:我不明白为什么我必须取消定义 :class:instance_of?。我可以看到 BasicObject 定义了 :== 所以我不得不取消定义它但是那两个呢?我查看了 BasicObject 文档和一些 C 代码,但没有找到任何内容。我同样查看了 Delegator 文档和代码,也没有找到任何东西。Delegator 似乎包含了 Kernel 模块,但是 Kernel#class 还是 Kernel#instance_of?不存在。

这两个方法是从哪里来的?如果它们根本没有实现,为什么我需要取消定义它们?我想我一定是遗漏了一些关于 Ruby 的对象模型之类的东西。

谢谢。

最佳答案

您可以通过检查方法得到提示:

Decorator.instance_method(:class)
# => #<UnboundMethod: Decorator(#<Module:0x00000102137498>)#class>

方法的所有者是 Decorator但实际上在 #<Module:0x00000102137498> 中定义.所以有一个匿名模块定义了它。有趣...让我们看看:

Decorator.ancestors
# => [Decorator, Delegator, #<Module:0x00000102137498>, BasicObject]

又是那个模块,在Delegator之间和 BasicObject .所以Delegator不直接派生自 BasicObject .如果您查看 lib/delegate.rb 中的源代码你发现:

class Delegator < BasicObject
kernel = ::Kernel.dup
kernel.class_eval do
[:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m|
undef_method m
end
end
include kernel
# ...

因此 Kernel 的副本制作模块,没有to_s , inspect , 等等...但仍然有 classinstance_of? .它包含在 Delegator 中这就是它们的来源。

请注意 Object通过包含 Kernel 继承相同的方法模块(但它当然包括完整的模块):

42.method(:class) # => #<Method: Fixnum(Kernel)#class>

这在 Object doc 中说明:

Object mixes in the Kernel module, making the built-in kernel functions globally accessible. Although the instance methods of Object are defined by the Kernel module, we have chosen to document them here for clarity.

关于ruby - Delegator 通过 BasicObject 透明化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11402796/

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