Using super()
¶
The idiomatic way to call methods on a superclass
is using the super()
object to resolve methods
in a super class:
class MyObject(NSObject):
def init(self):
self = super().init()
if self is None:
return None
...
return self
Because of the way PyObjC is implemented you cannot
use the builtin super
for this, but must use
PyObjC’s reimplementation of this builtin:
from objc import super
You must use this exact pattern to use the argumentless
version of super
, using objc.super()
in a method
body will result in runtime errors due to the way
the argumentless super fetches the defining class of
the method.
Using this pattern is safe to use in modules that
contain a mix of Python and Cocoa classes, PyObjC’s
super
reimplements the builtin super
with some
additions to support PyObjC.
Background¶
PyObjC lazily fills a class __dict__
for two reasons:
Correctness: Cocoa classes can change at runtime by way of using categories loaded from dynamic libraries. Because of this eagerly scanning classes for methods can result in an incomplete
__dict__
. Furthermore the Objective-C runtime does not have way to effiencly detect changes to a class.Performance: Cocoa contains a large number of classes with an even larger number of methods. Eagerly scanning classes has a significant overhead when importing framework bindings.
In itself a lazily filled does not cause a problem because the
attribute gets filled as needed. But this is a problem with the
builtin super
because that walks the MRO and directly peeks
in the class __dict__
without a way to intercept this. Because
of this objc.super
is a reimplementation of builtin.super
with special behaviour for Cocoa classes.