递归复制子类?
这个类叫做 Event
,里面有两个功能,一个是 copyFrom(self, event)
,另一个是 copy(self)
。这两个功能的实现其实很简单,就像做蛋糕一样容易。
class Event(object):
def __init__(self, a, b):
self.a = a
self.b = b
def copyFrom(self, event):
self.a = event.a
self.b = event.b
def copy(self):
return Event(self.a, self.b)
现在,子类 MouseEvent
想要重写这两个功能。第一个功能 copyFrom(self, event)
可以通过调用父类的方法来实现。
class MouseEvent(Event):
def __init__(self, a, b, c, d):
super(Event, self).__init__(a, b)
self.c = c
self.d = d
def copyFrom(self, event):
super(Event, self).copyFrom(event)
self.c = event.c
self.d = event.d
但是 copy(self)
呢?当然,创建一个新对象并不难。
# ...
def copy(self):
return MouseEvent(self.a, self.b, self.c, self.d)
但如果 Event
类里面有一些 私有 属性呢?想要继承这个类的人可不想去管这些私有属性!
class Event(object):
def __init__(self, a, b):
self.a = a
self.b = b
self._aab = fancyFunction(a, b)
def doStuff(self, c):
self._aab <<= c * 2
def copyFrom(self, event):
self.a = event.a
self.b = event.b
self._aab = event._aab
def copy(self):
e = Event(self.a, self.b)
e._aab = self._aab
return e
现在这个 copy(self)
的实现看起来就有点麻烦了,MouseEvent
重写的那个也是一样。
class MouseEvent(Event):
# ...
def copy(self):
e = MouseEvent(self.a, self.b, self.c, self.d)
e._aab = self._aab
return e
在这个例子中,我该如何实现一个简单的,可能是递归的 复制 行为呢?
1 个回答
3
首先,MouseEvent
的构造函数调用了Event
的构造函数,这样就够了吗?
如果不够的话,可以看看copy
模块。这个模块是基于pickle
的状态获取和恢复协议。通过这个协议,递归调用变得很简单。当然,如果你不想遵循pickle
的接口,你可以直接复制这个基本设计,但我觉得这样做没有什么好处。
编辑:看来我没有把我的意思表达清楚,我的回答可能有点模糊。所以这里有一个使用建议设计的代码示例:
class Event(object):
def __init__(self, a, b):
self.a = a
self.b = b
self._aab = fancyFunction(a, b)
def retrieve_state(self):
return self.a, self.b, self._aab
def restore_state(self, state):
self.a, self.b, self._aab = state
def copy_from(self, event):
self.restore_state(event.retrieve_state())
def copy(self):
e = object.__new__(self.__class__)
e.restore_state(self.retrieve_state())
return e
class MouseEvent(Event):
def __init__(self, a, b, c, d):
Event.__init__(self, a, b)
self.c = c
self.d = d
def retrieve_state(self):
event_state = super(MouseEvent, self).retrieve_state()
return event_state, self.c, self.d
def restore_state(self, state):
event_state, self.c, self.d = state
super(MouseEvent, self).restore_state(event_state)
注意,如果你把retrieve_state()
和restore_state()
分别改名为__getstate__()
和__setstate__()
,你甚至不需要copy()
和copy_from()
这两个方法,因为这样一来你就可以直接使用标准的copy()
模块了。(在这个情况下,你甚至不需要定义__getstate__()
和__setstate__()
,因为默认情况下会保存和恢复所有实例属性。)