gpt4 book ai didi

Ruby:将方法添加到输入参数的类中

转载 作者:太空宇宙 更新时间:2023-11-03 17:12:57 25 4
gpt4 key购买 nike

我只是在探索 ruby​​,并且想知道将方法添加到对象类的理论上的可能性。例如,定义一个接受参数的方法并将方法添加到该参数的类(而不仅仅是参数对象本身)。像这个例子:

class SomeClass
end

class AnotherClass
end

alpha = SomeClass.new
beta = AnotherClass.new

def AddHelloMethodTo param

# This is where I'm trying to
# add a method to the class of the parameter
def param.class.Hello
"Hello"
end

end

AddHelloMethodTo alpha
AddHelloMethodTo beta

gamma = AnotherClass.new

alpha.Hello
beta.Hello
gamma.Hello

(如果我有语法错误/打字错误,请原谅我真的是新手!)
请注意,我没有在 gamma 上调用 AddHelloMethodTo,但我希望 Hello 被定义,因为我将它添加到了类中。
这可能吗?

最佳答案

这是最接近您所拥有的。我冒昧地将其更改为标准 Ruby 编码风格,但请注意,唯一真正的更改是 add_hello_method_to_class_of 的第一行:

class SomeClass; end
class AnotherClass; end

alpha = SomeClass.new
beta = AnotherClass.new

def add_hello_method_to_class_of(obj)
obj.class.send(:define_method, :hello) do
'Hello'
end
end

add_hello_method_to_class_of(alpha)
add_hello_method_to_class_of(beta)

gamma = AnotherClass.new

alpha.hello
beta.hello
gamma.hello

原来,你有

def obj.class.hello

这会起作用,但它不会像您认为的那样工作。这会将一个单例方法 添加到类对象 本身,但您似乎假设它会添加一个实例方法。如果你想添加一个实例方法,你需要像这样使用Module#define_method:

obj.class.define_method(:hello)

除了Module#define_methodprivate,所以你需要使用反射来规避访问限制:

obj.class.send(:define_method, :hello)

请注意,我还将方法的名称从 add_hello_method_to 更改为 add_hello_method_to_class_of,因为它不会添加 hello 方法添加到它的参数,它将它添加到它的参数的

但是,如果你像这样进行猴子修补,通常认为使用 mixin 是一种很好的做法,从那时起,mixin 就会出现在对象的继承链中,这给任何调试该代码的人至少留下了一个战斗的机会来找出看看那个神秘的 hello 方法到底是从哪里来的:

# file: hello_extension.rb
module HelloExtension
def hello
'Hello'
end
end

def add_hello_method_to_class_of(obj)
obj.class.send(:include, HelloExtension)
end

# some other file
require 'hello_extension'

class SomeClass; end
class AnotherClass; end

alpha = SomeClass.new
beta = AnotherClass.new

add_hello_method_to_class_of(alpha)
add_hello_method_to_class_of(beta)

gamma = AnotherClass.new

alpha.hello
beta.hello
gamma.hello

现在,您可以轻松调试此代码:

gamma.class.ancestors
# => [AnotherClass, HelloExtension, Object, Kernel, BasicObject]

如果有人想知道 hello 方法是从哪里来的,那么很容易弄清楚一个名为 HelloExtension 的 mixin 可能与它有关.遵循标准的 Ruby 命名约定,他们甚至知道查看名为 hello_extension.rb

的文件

你甚至可以这样做:

gamma.method(:hello).source_location
# => ['hello_extension.rb', 3]

关于Ruby:将方法添加到输入参数的类中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4515725/

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