继承:基类方法返回自身实例

4 投票
3 回答
737 浏览
提问于 2025-04-17 22:53

我的基类里面有一个方法,这个方法会返回它自己的一个实例。当我写子类的时候,有没有办法让这个实例变成我的子类的实例,而不是基类的实例呢?而且我不想修改基类的代码,也不想把整个基类的方法重写到我的子类里。

举个例子:

class A:
    def __init__(self,x):
        self.x = x
    def add(self):
        self.x += 2
    def new(self,z):
        n = A(z)
        return n

class B(A):
    def __init__self():
        A.__init__(self,x)

在这里,如果我这样做:

a = B(10)
b = a.new(4)

那么b会是A的一个实例,而不是我想要的B的实例。在这个简单的例子里,我可以在B类里重写这个方法,但在我的程序中我不想这样做,因为这样会影响可移植性,因为我无法控制基类,因为它是另一个包的一部分。

有没有什么办法可以做到这一点呢?

3 个回答

0

使用 __class__

n = self.__class__(z)
return n

...

@jonrsharpe 的回答更好

1

理想情况下,你应该这样做,而不是:

def new(self,z):
    n = A(z)
    return n

你应该有:

def new(self, z):
    n = self.__class__(z)
    return n

这样一来,你就可以使用调用方法的实例的类,而不是硬编码你正在创建的新实例的类。

不过,既然你提到不能修改基类,你有两个选择:

  1. 在派生类中重写这个方法
  2. 对基类进行猴子补丁
  3. 请求维护基类的人为你做这个修改

你说你不想重写它,因为这对可移植性不好。我认为这并不完全正确——如果基类可能会更新,导致它的公共接口行为发生变化,那它本身就已经对可移植性不好了,因为谁知道会引入什么破坏性变化。如果行为会保持一致(即使实现有所变化),那么重写应该是安全的。

另一个选择是对基类进行猴子补丁。这会和在基类中重写一样有问题,不同的是其他子类也会得到这种行为,而不仅仅是那些继承自B的子类。

你可以这样进行猴子补丁(在类定义之外):

def new_new(self, z):
    n = self.__class__(z)
    return n

A.new = new_new
2

把它变成一个类的方法:

@classmethod
def new(cls, z):
    return cls(z)

撰写回答