2013-02-26 1 views
1

Я портирую небольшую библиотеку Objective-C/Cocoa в Python/PyObjC. И я смущаюсь о том, как реализовать.Как наследовать NSPanel в 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. initContentRect HUDWindow переопределению initContentRect NSPanel в.
  2. Внутри initContentRect HUDWindow вызывается initContentRect от NSPanel и получает результат как «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?

ответ

1

Ваше первое решение находится на правильном пути. Во втором случае вам нужно либо использовать NSProxy, либо написать свою собственную явную делецию, которая является болью (а третья - не способ сделать это). может сделать что-то подобное с помощью swizzling, но не).

Однако есть несколько проблем.

Во-первых, этот код:

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.х:

self = super(HUDWindow, self).initWithContentRect_styleMask_backing_defer_(rect, NSBorderlessWindowMask, buf, flag) 

В ObjC, super не суперкласса, но особый магический объект, который эффективно «я как экземпляр суперкласса». Это почти так же, как Python 3's super(), или менее волшебный Python 2 super, а PyObjC делает дополнительную работу, чтобы вы могли игнорировать это «почти».

Что вы делали, (пытаясь) инициализировать NSPanel объект класса (или, может быть объект класса моста PyObjC к NSPanel, я не уверен, какой), или, возможно, даже пытается инициализировать rect как если он были NSPanel. Независимо от того, что вы делаете, он не может ничего сделать для инициализации вашего экземпляра self. (И присвоение результата self не делает то же самое в Python, как в ObjC. Это все еще обычно идиоматический стиль в PyObjC, но не вводите его в заблуждение, единственный эффект, который он имеет, заключается в том, что вы снова используете self в пределах Инициализатор. Во всяком случае, в лучшем случае это скроет проблему в ObjC, не исправит ее ...) Итак, после возврата из этого метода ваш self все еще является выделенным, но неинициализированным экземпляром NSPanel, который был до того, как вы что-то назвали.

Это объясняется в основном в начале учебника, в Two Phase Instantiation.

+0

Спасибо @abamert! Ваш ответ содержит все, что я хочу (и нужно) знать! Я не могу не сказать «Эврика!». – user2100702

 Смежные вопросы

  • Нет связанных вопросов^_^