我正在编写一个类,其中实例变量具有,以便在初始化期间进行设置,或者该类无法正常工作。该类设计为大量子类,我不希望所有子类必须在super
重载中调用initialize
,所以我想在之前设置实例变量 调用初始化函数。
在调用Class#new
函数之前,是否可以通过重载initialize
或类似的东西来进行一些自定义实例初始化?
像:
class Foo < MySuperClass
def initialize
# @foo is already set to 123 because of the magic in MySuperClass
assert @foo == 123
end
end
答案 0 :(得分:3)
您可以使用模板方法模式,而不是依赖于子类中的#initialize
,如下所示:
class Parent
def initialize
@foo = 123
my_initialize
end
# Concrete classes must override
def my_initialize
raise NoMethodError
end
end
class Child < Parent
def my_initialize
puts @foo
end
end
另一种方法,如果你不想使用模板方法,那么prepend
是一个包含初始化逻辑的模块(在Ruby 2中添加了prepend
):
class Parent
def self.inherited(class_name)
class_name.prepend Initializer
end
module Initializer
def initialize
# Your initialization code
@foo = 123
# Call your child class's initialize
super
end
end
end
class Child < Parent
def initialize
puts @foo
end
end
以下是关于Module#prepend:http://gshutler.com/2013/04/ruby-2-module-prepend/
的优秀入门读物答案 1 :(得分:0)
延迟初始化
class MySuperClass
protected
def foo
@foo ||= 123
end
end
class Foo < MySuperClass
def initialize
assert foo == 123
end
end
答案 2 :(得分:0)
我在this forum thread找到了一个有趣的方式:
class MySuperClass
def self.new(*args, &block)
instance = allocate()
# Pre-initialize
instance.instance_variable_set(:@foo, 123)
instance.send(:initialize, *args, &block)
return instance
end
end
这会覆盖默认的Class.new
方法并手动创建实例。这意味着我可以在调用initialize
之前跳转并设置实例变量。