Reputation: 16870
The class Event
implements a function copyFrom(self, event)
and copy(self)
. The implementation of both methods is simple made cake.
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)
Now, the subclass MouseEvent
wants to override both of them. The first method, copyFrom(self, event)
can be implemented by calling the super-method.
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
But what about copy(self)
? Of course, just creating a new object is not hard.
# ...
def copy(self):
return MouseEvent(self.a, self.b, self.c, self.d)
But what if the Event
class owns some private attributes ? The person that wants to subclass it, does not want to care about them !
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
This implementation of copy(self)
looks quite dirty now, and so does the overriden one from MouseEvent
.
class MouseEvent(Event):
# ...
def copy(self):
e = MouseEvent(self.a, self.b, self.c, self.d)
e._aab = self._aab
return e
How can I implement an easy, maybe recursive, copy-behaviour in this particular example ?
Upvotes: 1
Views: 562
Reputation: 601569
First, isn't it enough that the MouseEvent
constructor recursively calls the Event
constructor?
If not, have a look at the copy
module. It is based on pickle
's state retrieval and restoration protocol. Using this protocol, recursive calls are easy. You could of course just copy this basic design if you don't want to conform to the pickle
interface, by I don't see any advantage to doing so.
Edit: It seems I failed to get across the message, and indeed my answer might be a bit vague. So here we go with a code example using the suggested design:
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)
Note that you wouldn't even need the copy()
and copy_from()
methods if you would simply rename retrieve_state()
and restore_state()
to __getstate__()
and __setstate__()
, respectively, because after toding this you can just use the standard copy()
module. (And in the case at hand, you wouldn't even need to define __getstate__()
and __setstate__()
at all, since the default behaviour is to save and restore all instance attributes.)
Upvotes: 3