抽象这种模式的最佳方法是什么:
class MyClass
attr_accessor :foo, :bar
def initialize(foo, bar)
@foo, @bar = foo, bar
end
end
Run Code Online (Sandbox Code Playgroud)
一个好的解决方案应该考虑超类,并且能够处理仍然能够使用初始化程序来执行更多操作.在您的解决方案中不牺牲性能的额外要点.
已经(部分)存在该问题的解决方案,但如果您希望在类中使用更具说明性的方法,则以下内容应该有效.
class Class
def initialize_with(*attrs, &block)
attrs.each do |attr|
attr_accessor attr
end
(class << self; self; end).send :define_method, :new do |*args|
obj = allocate
init_args, surplus_args = args[0...attrs.size], args[attrs.size..-1]
attrs.zip(init_args) do |attr, arg|
obj.instance_variable_set "@#{attr}", arg
end
obj.send :initialize, *surplus_args
obj
end
end
end
Run Code Online (Sandbox Code Playgroud)
你现在可以这样做:
class MyClass < ParentClass
initialize_with :foo, :bar
def initialize(baz)
@initialized = true
super(baz) # pass any arguments to initializer of superclass
end
end
my_obj = MyClass.new "foo", "bar", "baz"
my_obj.foo #=> "foo"
my_obj.bar #=> "bar"
my_obj.instance_variable_get(:@initialized) #=> true
Run Code Online (Sandbox Code Playgroud)
该解决方案的一些特征:
initialize_withinitialize进行自定义初始化super在initializeinitialize是指定的属性未使用的参数initialize_withinitialize_with是继承的,但在子类上定义新集将删除父属性如果要创建具有绝对最小性能开销的解决方案,将大多数功能重构为字符串并不困难,可以在eval定义初始化程序时对其进行编辑.我没有确定差异的基准.
注意:我发现黑客攻击new比黑客攻击更好initialize.如果initialize使用元编程定义,则可能会出现将块传递initialize_with给替代初始值设定项的情况,并且无法super在块中使用.
| 归档时间: |
|
| 查看次数: |
5625 次 |
| 最近记录: |