gpt4 book ai didi

ruby - 在 Ruby 中,围绕子方法执行 block 的最佳方法是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 08:29:54 25 4
gpt4 key购买 nike

我有一个父类:

class Base
def my_method
block_method do
# EXECUTE WHATEVER'S IN THE CHILD VERSION OF my_method
# HOW TO DO?
end
end

def block_method
original_foo = 'foo'
foo = 'CUSTOM FOO'

yield

foo = original_foo
end
end

和一些子类——目前有五个,以后还会有更多:

class ChildA < Base
def my_method
puts 'apple'
puts 'aardvark'
end
end

class ChildE < Base
def my_method
puts 'eel'
puts 'elephant'
end
end

我只想在每个 Child#my_method 期间更改变量所指的内容。

我的想法是通过将每个 Child#my_method 的功能包装在一个 block 中来实现这一点。但我宁愿在父类中这样做,也不愿将每个子类的 #my_method 包装在完全相同的 block 中。

关于我如何做到这一点的任何见解?

如果 super 有一些相反的东西,我想那将是完成我想做的事情的一种方式。

最佳答案

您可以使用模块和 prepend 给出您所谓的“与 super 相反”的概念,如下所示:

module MethodThing
# added to remove binding from class since
# #my_method relies on the existence of #foo and #foo=
def self.prepended(base)
base.attr_reader(:foo) unless base.method_defined?(:foo)
base.attr_writer(:foo) unless base.method_defined?(:foo=)
end
def my_method
puts "Before: #{foo}"
original_foo = foo
self.foo= 'CUSTOM FOO'
begin
super
rescue NoMethodError
warn "(skipped) #{self.class}##{__method__} not defined"
end
self.foo = original_foo
puts "After: #{foo}"
end
end

在继承前添加模块

class Base 
def self.inherited(child)
child.prepend(MethodThing)
end

attr_accessor :foo
def initialize
@foo = 12
end
end


class ChildA < Base
def my_method
puts 'apple'
puts "During: #{foo}"
puts 'aardvark'
end
end

class ChildE < Base
end

输出:

ChildA.new.my_method
# Before: 12
# apple
# During: CUSTOM FOO
# aardvark
# After: 12
ChildE.new.my_method
# Before: 12
# (skipped) ChildE#my_method not defined
# After: 12

还有其他一些奇怪的方法可以通过继承来实现这一点,例如

class Base
class << self
attr_accessor :delegate_my_method
def method_added(method_name)
if method_name.to_s == "my_method" && self.name != "Base"
warn "#{self.name}#my_method has been overwritten use delegate_my_method instead"
end
end
end
attr_accessor :foo

def my_method
puts "Before: #{foo}"
original_foo = foo
self.foo= 'CUSTOM FOO'
begin
method(self.class.delegate_my_method.to_s).()
rescue NameError, TypeError
warn "(skipped) #{self.class} method delegation not defined"
end
self.foo = original_foo
puts "After: #{foo}"
end
end

class ChildA < Base
self.delegate_my_method = :delegation_method

def delegation_method
puts 'apple'
puts "During: #{foo}"
puts 'aardvark'
end
end

我可能会继续使用越来越陌生的方法来解决这个问题,但我认为这些方法会让您到达需要去的地方。

关于ruby - 在 Ruby 中,围绕子方法执行 block 的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49563339/

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