1

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を継承すると記載されています。私がコードを読んでいる限り、初期化は次のように進行しています。

  1. HUDWindowのinitContentRectは、NSPanelのinitContentRectをオーバーライドします。
  2. HUDWindowのinitContentRect内で、NSPanelのinitContentRectが呼び出され、結果が「self」として取得されます。

まず、このような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のようなクラスを継承する一般的な方法はありますか?

4

1 に答える 1

1

あなたの最初の解決策は正しい道にあります。NSProxy2番目の方法では、独自の明示的な委任を使用または作成する必要がありますが、これは面倒です(3番目の方法はそれを行う方法ではありません。スウィズリングを使用して同様のことを行うことはできますが、できません)。

ただし、いくつかの問題があります。

まず、このコード:

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はスーパークラスではありませんが、事実上「スーパークラスのインスタンスとしての自己」である特別な魔法のオブジェクトです。super()これは、Python3またはそれほど魔法ではないPython2とほぼ同じsuperであり、PyObjCは、その「ほぼ」を無視できることを意味する追加の作業を行います。

あなたが行っていたのは、NSPanelクラスオブジェクト(またはPyObjCブリッジのクラスオブジェクトを初期化しようとしたことですが、どちらかはわかりNSPanelません)、あるいはrectそれがであるかのように初期化しようとしたことNSPanelです。何をしていても、インスタンスを初期化するために何もできない可能性がありselfます。(そして、結果をに割り当てることはself、PythonではObjCと同じことをしません。それは、通常、PyObjCでは慣用的なスタイルですが、誤解しないでください。唯一の効果はself、イニシャライザメソッド内で再度使用する場合です。とにかく、せいぜいObjCの問題をカバーし、修正しないでください…)したがって、このメソッドから戻った後も、何かを呼び出す前selfの、割り当てられているが初期化されていないインスタンスです。NSPanel

これは主に、チュートリアルのかなり早い段階である2フェーズインスタンス化で説明されています。

于 2013-02-26T23:06:55.413 に答える