代码之家  ›  专栏  ›  技术社区  ›  UlfR

我可以从超类实例化子类对象吗

  •  4
  • UlfR  · 技术社区  · 17 年前

    class A(object):
        def __init__(self, id):
            self.myid = id
        def foo(self, x):
            print 'foo', self.myid*x
    
    class B(A):
        def __init__(self, id):
            self.myid = id
            self.mybid = id*2
        def bar(self, x):
            print 'bar', self.myid, self.mybid, x
    

    使用时,可生成以下内容:

    >>> a = A(2)
    >>> a.foo(10)
    foo 20
    >>> 
    >>> b = B(3)
    >>> b.foo(10)
    foo 30
    >>> b.bar(12)
    bar 3 6 12
    

    现在让我们假设我还有一些子类 class C(A): class D(A): . 我也知道id将始终适合B、C或D,但决不能同时适合其中两个。

    现在我想调用A(23)并获得正确子类的对象。大概是这样的:

    >>> type(A(2))
    <class '__main__.B'>
    >>> type(A(22))
    <class '__main__.D'>
    >>> type(A(31))
    <class '__main__.C'>
    >>> type(A(12))
    <class '__main__.B'>
    

    3 回复  |  直到 13 年前
        1
  •  6
  •   Abgan    17 年前

    你应该实施 Abstract Factory pattern ,然后您的工厂将根据提供的参数生成您喜欢的任何对象。这样,您的代码将保持干净和可扩展性。

    当您升级解释器版本时,可以删除任何可以直接使用的hack,因为没有人期望向后兼容来保留这些东西。

    编辑:过了一段时间,我不确定是否应该使用抽象工厂,或者 Factory Method pattern . 这取决于代码的细节,因此适合您的需要。

        2
  •  2
  •   Rob Wells    17 年前

    一般来说,当超类了解子类时,这不是一个好主意。

    超类为该类型的所有对象(例如动物)提供通用行为。然后,子类提供行为的专门化,例如狗。

    从“isa”关系的角度考虑,即狗是动物。

    动物就是狗,这是没有道理的。

    干杯

    抢劫

        3
  •  2
  •   che    17 年前

    我不认为您可以更改对象的类型,但是您可以创建另一个类,该类的工作方式类似于子类的工厂。大概是这样的:

    class LetterFactory(object):
        @staticmethod
        def getLetterObject(n):
            if n == 1:
                return A(n)
            elif n == 2:
                return B(n)
            else:
                return C(n)
    
    a = LetterFactory.getLetterObject(1)
    b = LetterFactory.getLetterObject(2)
    ...