Lesson #1: Don’t forget to return self when you override init. Otherwise nothing works, but it isn’t obvious why.
Lesson #2: Initialize instance variables in init. I started out trying to avoid overriding init whenever possible. Perhaps it was because I was gunshy after learning Lesson #1 the hard way. Also, I don’t like the two lines of boilerplate that begin every overridden init:
class MyObject(NSObject):
def init(self):
self = super(MyObject, self).init()
if self is None: return None
One of the great things about Python is its terseness, and having to type that stuff every time is annoying. I think that if I knew enough Python I could write a function decorator to handle the obligatory call to superclass, but then I’d have to add the decorator module to the project and import it — not a big savings in typing.
So when I needed to initialize an instance variable I tried to avoid overriding init, and instead would perform the initialization in the class definition:
class MyObject(NSObject):
_array = []
_lastIndex = 0
...etc...
That way instance methods could refer to self.instance-variable-name and get the initialized class attribute if no per-instance value had yet been set. Having that series of assignments at the top of the class definition also served to gather together all the instance variable names I planned to use, rather than having them scattered through the code.
But experienced Python programmers will immediately spot the problem. Objects assigned to class attributes are shared between all the instances of the class, and so changes made to mutable objects by one instance are seen by all the others. If instance A added an item to self._array, instance B’s self._array would have it as well.
That was not at all what I wanted. So I’ve gone back to overriding init whenever I need to initialize instance variables.
Posted by Jim Matthews
Posted by Jim Matthews