继承:基类方法返回自身实例
我的基类里面有一个方法,这个方法会返回它自己的一个实例。当我写子类的时候,有没有办法让这个实例变成我的子类的实例,而不是基类的实例呢?而且我不想修改基类的代码,也不想把整个基类的方法重写到我的子类里。
举个例子:
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
这样一来,你就可以使用调用方法的实例的类,而不是硬编码你正在创建的新实例的类。
不过,既然你提到不能修改基类,你有两个选择:
- 在派生类中重写这个方法
- 对基类进行猴子补丁
- 请求维护基类的人为你做这个修改
你说你不想重写它,因为这对可移植性不好。我认为这并不完全正确——如果基类可能会更新,导致它的公共接口行为发生变化,那它本身就已经对可移植性不好了,因为谁知道会引入什么破坏性变化。如果行为会保持一致(即使实现有所变化),那么重写应该是安全的。
另一个选择是对基类进行猴子补丁。这会和在基类中重写一样有问题,不同的是其他子类也会得到这种行为,而不仅仅是那些继承自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)