给定一个类层次结构如下:
class A
def initialize(param)
if param == 1 then
#initialize and return instance of B
else
#initialize and return instance of C
end
end
end
class B < A
end
class C < A
end
是否有可能实际初始化并返回一个实例B
或C
初始化时A
? 即my_obj = A.new(param)
将导致my_obj
是类的一个实例B
或C
取决于的值param
,它获取在检查A.initialize(param)
在我的用例其仅在运行时知子(其中B
或C
)使用和父类( A
)基本是从来没有真正使用。 我想这可能是移动决定是否逻辑是一个好主意B
或C
到他们的共同祖先。
如果这是不可能的(或不良作风),我应该在哪里放的检查param
和阶级决定初始化?
你在这里打破了基本原则,面向对象 - 类应一无所知它们的子类。 当然,有时原则应被打破,但没有明显的原因,在这里做了。
一个更好的解决方案是将实例化逻辑在一个单独的类转移到工厂方法。 工厂方法采用相同的参数A的初始值设定的上方,并返回适当的类的一个实例。
问题是,返回值initialize
将被忽略。 这里是当你调用会发生什么A.new
:
-
new
呼叫称为一类特殊的方法allocate
-这返回类的空实例 -
new
然后调用initialize
返回的对象allocate
,并返回对象
做你想做的事,你需要重写new
,使它做你想要什么:
class A
def self.new(args*)
if(args[0]==1)
B.new(*args[1..-1])
else
C.new(*args[1..-1])
end
end
end
还有别的东西,虽然考虑。 如果A
是从来没有单独使用,你应该使用某种工厂方法,或者,只是一个简单的if语句。 例如:
def B_or_C(param,args)
(param == 1 ? B : C).new(args)
end
设计真的取决于你使用的是他们为了什么。 当你,例如,有可能被用来处理的东西多个版本,例如一类,HTML,你可以有一个主类HTMLParser
其推翻new
和可能回到它的任何子类: HTML1Parser
, HTML2Parser
, HTML3Parser
, HTML4Parser
和HTML5Parser
。
注意:您必须重写new
在子类的默认方法,以防止无限循环:
def self.new(args*)
obj=allocate
obj.send(:initialize, *args)
obj
end