gpt4 book ai didi

ruby - 带 block 的动态类定义

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

所以我遇到了这种情况,我想以编程方式定义一堆类。我在下面使用的方法工作正常,除了我从这里继承的第 3 方类不喜欢该类是匿名定义的事实(基本上,它没有它需要的信息,即. 在我有机会将匿名类设置为常量之前,在“继承” Hook 中的类名)。

['one', 'two', 'three'].each do |model|
cls = Class.new(ThirdPartyClass) do
define_method :model do
model
end
end
ThirdPartyClass.const_set(model.capitalize, cls)
end

我可以简单地使用 eval 并定义类似这样的类:

['one', 'two', 'three'].each do |model|
eval "class ThirdPartyClass::#{model.capitalize} < ThirdPartyClass; ...; end"
end

但我不喜欢它,因为它是困惑的字符串插值。从美学角度来看,基于 block 的方法似乎“更好”。

有什么方法可以使用基于 block 的语法以非匿名方式定义该类(即从一开始就使用名称),还是我注定要留在 eval 的困惑字符串输入中?

最佳答案

Class#inherited 回调在创建类时被调用。当实例化一个匿名类时,这总是在类可以被分配给常量之前,为其分配一个名称。我看不出有什么办法可以解决这个问题。您可以最小化字符串 eval 中的代码量,方法是使用 eval 创建一个空类,使用特殊的类语法使名称在 inherited 之前可见,然后跟进 block 形式的 class_eval 来定义您的方法。

class Super
def self.inherited(child)
puts "#{self.name} inherited by #{child.inspect} named '#{child.name}'"
end
end

# Your way, inherited can't see name
['one', 'two', 'three'].each do |model|
klassname = model.capitalize
klass = Class.new(Super) do
puts "defining #{model} inheriting from Super"
define_method :model do
model
end
end
Super.const_set(klassname, klass)
end

# this way inherited sees name because we use special class definition syntax in minimal string eval
['four', 'five', 'six'].each do |model|
klassname = model.capitalize

eval %Q{
class Super::#{klassname} < Super
puts %Q[defining Super::#{klassname} inheriting from Super]
end
}

Super.const_get(klassname).class_eval do
puts "defining methods for Super::#{klassname} inheriting from Super"
define_method :model do
model
end
end
end

# produces:
Super inherited by #<Class:0x0000010084c988> named ''
defining one inheriting from Super
Super inherited by #<Class:0x0000010084c640> named ''
defining two inheriting from Super
Super inherited by #<Class:0x0000010084c320> named ''
defining three inheriting from Super
Super inherited by Super::Four named 'Super::Four'
defining Super::Four inheriting from Super
defining methods for Super::Four inheriting from Super
Super inherited by Super::Five named 'Super::Five'
defining Super::Five inheriting from Super
defining methods for Super::Five inheriting from Super
Super inherited by Super::Six named 'Super::Six'
defining Super::Six inheriting from Super
defining methods for Super::Six inheriting from Super

关于ruby - 带 block 的动态类定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14364113/

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