假设你有一个具体类
class Knight(object):
def __init__(self, name):
self._name = name
def __str__(self):
return "Sir {} of Camelot".format(self.name)
现在碰巧类层次结构必须改变。 Knight
应该成为一个抽象基类,为各种城堡的骑士提供一堆具体的子类。很简单:
class Knight(metaclass=ABCMeta): # Python 3 syntax
def __str__(self):
return "Sir {} of {}".format(self.name, self.castle)
@abstractmethod
def sing():
pass
class KnightOfTheRoundTable(Knight):
def __init__(self, name):
self.name = name
@property
def castle(self):
return "Camelot"
@staticmethod
def sing():
return ["We're knights of the round table",
"We dance whenever we're able"]
但现在所有使用Knight("Galahad")
构造Knight
的代码都被破坏了。相反,我们可以保持 Knight
不变,并引入一个 BaseKnight
,但是随后检查 isinstance(x, Knight)
的代码应该继续工作任何骑士都可能需要改为检查 BaseKnight
。
如何将一个具体类变成一个抽象类,同时避免构造函数和 isinstance
检查?
最佳答案
使现有类成为基类,但是overload __new__
在尝试实例化基类时返回子类:
class Knight(metaclass=ABCMeta):
def __new__(cls, *args, **kwargs):
if cls is Knight:
# attempt to construct base class, defer to default subclass
return KnightOfTheRoundTable(*args, **kwargs)
else:
obj = super(Knight, cls).__new__(cls)
obj.__init__(*args, **kwargs)
return obj
def __str__(self):
return "Sir {} of {}".format(self.name, self.castle)
@abstractmethod
def sing():
pass
现在 Knight("Galahad")
继续工作但返回一个 KnightOfTheRoundTable
。 isinstance(Knight("Robin"), Knight)
返回 True
,与 isinstance(x, Knight)
检查任何其他子类实例一样.
关于python - 使具体类抽象,保留构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26462167/