我正在将一个Objective-C / Cocoa的小型库移植到Python / PyObjC中。 而且我对实施的方式感到困惑。
原始代码如下所示:
@implementation HUDWindow
- (id)initWithContentRect:(NSRect)contentRect
styleMask:(unsigned int)styleMask
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag
{
if (self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:bufferingType
defer:flag]) {
// initialize code here
:
:
:
:
:
:
return self;
}
}
在头文件中说HUDWindow类继承了NSPanel。 至于我阅读代码,初始化是这样的进展:
首先,我编写这样的python代码。这是一个逐字翻译:
class HUDWindow(NSPanel):
def initWithContentRect_styleMask_backing_defer_(self, rect, style, buf, flag):
self = NSPanel.initWithContentRect_styleMask_backing_defer_(
rect, NSBorderlessWindowMask, buf, flag)
# initialize code here
:
:
:
:
:
:
return self
它无效,因为self
只是NSPanel
的一个实例。我无法调用我从原始obj-c代码中移植的任何上瘾函数。
所以我改变了我的代码:
class HUDWindow(NSPanel):
def initWithContentRect_styleMask_backing_defer_(self, rect, style, buf, flag):
self.window = NSPanel.initWithContentRect_styleMask_backing_defer_(
rect, NSBorderlessWindowMask, buf, flag)
# initialize code here
:
:
:
:
:
:
return self.window
效果好一点。至少,我可以在这个初始化函数中调用其他函数。 但是在初始化函数之外,我无法调用从原始代码移植的其他函数。
所以我试过这样:
class HUDWindow(NSPanel):
def initWithContentRect_styleMask_backing_defer_(self, rect, style, buf, flag):
self.window = NSPanel.initWithContentRect_styleMask_backing_defer_(
rect, NSBorderlessWindowMask, buf, flag)
# initialize code here
:
:
:
:
:
:
self.window.setTitle_ = self.setTitle_
return self.window
它不起作用。在制作实例后我无法覆盖或添加函数。
现在我觉得我做错了。是否有任何常用的方法来继承像NSPanel或NPWindow这样的类?
答案 0 :(得分:1)
您的第一个解决方案是在正确的道路上。在第二种情况下,您需要使用NSProxy
或编写自己的显式委托,这很痛苦(第三种不是这样做的方式 - 您可以做类似的东西通过调配,但不要)。
然而,有一些问题。
首先,这段代码:
self = NSPanel.initWithContentRect_styleMask_backing_defer_(rect, NSBorderlessWindowMask, buf, flag)
...相当于这个ObjC代码:
self = [NSPanel initWithContentRect:rect
styleMask:NSBorderlessWindowMask
backing:buf
defer:flag]
......当你想要的是:
self = [super initWithContentRect:rect
styleMask:NSBorderlessWindowMask
backing:buf
defer:flag]
后者的PyObjC等价物是:
self = super().initWithContentRect_styleMask_backing_defer_(rect, NSBorderlessWindowMask, buf, flag)
或者,在2.x:
self = super(HUDWindow, self).initWithContentRect_styleMask_backing_defer_(rect, NSBorderlessWindowMask, buf, flag)
在ObjC中,super
不是超类,而是一个特殊的魔术对象,它实际上是“自我作为超类的一个实例”。它几乎就像Python 3的super()
,或者不那么神奇的Python 2 super
,PyObjC做了额外的工作,意味着你可以忽略“差不多”。
你正在做的是(尝试)初始化NSPanel
类对象(或者可能是PyObjC桥的类对象到NSPanel
,我不确定哪个),或者甚至可能尝试将rect
初始化为好像是NSPanel
。无论你做什么,它都不可能做任何事情来初始化你的self
实例。 (并将结果分配给self
并不像在ObjC中那样在Python中执行相同的操作。它在PyObjC中通常仍然是惯用的样式,但不要被它误导;它唯一的作用就是如果你使用它初始化方法中再次self
。无论如何,最好能够掩盖ObjC中的问题,而不是修复它......)因此,从这个方法返回后,你的self
仍然是分配的但是在您调用任何内容之前的未初始化NSPanel
实例。
本教程很早就在Two Phase Instantiation中解释了这一点。