如何在初始化父类返回子类的新实例?(How to return new instance of su

2019-07-29 23:52发布

给定一个类层次结构如下:

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

是否有可能实际初始化并返回一个实例BC初始化时A ? 即my_obj = A.new(param)将导致my_obj是类的一个实例BC取决于的值param ,它获取在检查A.initialize(param)

在我的用例其仅在运行时知子(其中BC )使用和父类( A )基本是从来没有真正使用。 我想这可能是移动决定是否逻辑是一个好主意BC到他们的共同祖先。

如果这是不可能的(或不良作风),我应该在哪里放的检查param和阶级决定初始化?

Answer 1:

你在这里打破了基本原则,面向对象 - 类应一无所知它们的子类。 当然,有时原则应被打破,但没有明显的原因,在这里做了。

一个更好的解决方案是将实例化逻辑在一个单独的类转移到工厂方法。 工厂方法采用相同的参数A的初始值设定的上方,并返回适当的类的一个实例。



Answer 2:

问题是,返回值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和可能回到它的任何子类: HTML1ParserHTML2ParserHTML3ParserHTML4ParserHTML5Parser

注意:您必须重写new在子类的默认方法,以防止无限循环:

def self.new(args*)
  obj=allocate
  obj.send(:initialize, *args)
  obj
end


文章来源: How to return new instance of subclass while initializing parent class?