2014-06-05 5 views
12

Le classi Swift hanno qualcosa come un puntatore isa che può essere rimappato?Swift isa puntatore remapping o altro metodo supportato swizzling

Abbiamo visto che Swift uses a more static method dispatch rispetto all'obiettivo-C, che (a meno che i dervizi di classe di Foundation/NSObject) impediscano lo stile di swizzling basato sulle implementazioni del metodo di remapping in fase di esecuzione.

Mi chiedo come implementeremo le funzioni dinamiche basate sull'interpretazione dei metodi come il pattern dell'osservatore, le notifiche, ecc.? Attualmente tutto questo materiale è fornito dal layer Objective-C e può essere facilmente integrato in Swift. Ma, se vogliamo fornire questo tipo di funzionalità in un framework (o app) del nostro, è necessario implementarle in Objective-C? Immagino che ci sia un modo per farlo 'nativamente'.

Un altro tipo di swizzling comune all'obiettivo-C sta rimappando il puntatore isa per generare al volo una sottoclasse. Questo tipo di swizzling è supportato in Swift? In caso contrario, è il modo supportato di intercettare invocazioni di metodi arbitrari?

Edit:Come @jatoben punti fuori, come di arm64 isa-rimappatura deve essere fatto chiamando object_setClass() e non accedendo direttamente il valore. Questo è ancora chiamato "isa pointer swizzling"

+0

Non è sicuro accedere a isa direttamente in Obj-C, o: http://sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html – jatoben

risposta

10

Sembra che sia lo scambio di metodi sia la tecnica di remapping del puntatore isa funzioni solo se la classe Swift ha NSObject come super-classe (direttamente o superiore). Al momento non funziona, quando la classe Swift non ha super-classe o qualche altra classe base non-Foundation.

Il seguente test mostra questo:

Classe: Birdy

class Birdy: NSObject {  
    func sayHello() 
    { 
     println("tweet tweet") 
    }  
} 

Classe: HodorBirdy

class HodorBirdy: Birdy { 

    override func sayHello() 
    { 
     super.sayHello() 
     println("hodor hodor") 
    } 
} 

prova:

func testExample() {   
    var birdy : Birdy = Birdy() 
    object_setClass(birdy, HodorBirdy.self) 
    birdy.sayHello(); 
} 

E l'uscita era come previsto:

tweet tweet 
hodor hodor 

In questo test sia la base di classe e sottoclasse sono stati creati in anticipo. Sebbene possano anche essere creati dinamicamente utilizzando il runtime Objective-C purché la classe abbia NSObject come antenato.

Quando una classe Swift non deriva dalla fondazione Objective-C, il compilatore favorirà l'invio basato su statico o vtable, quindi non è chiaro in che modo l'intercettazione del metodo funzionerà affatto in questo caso!

A meno che il linguaggio/compilatore non ne faccia una specifica indennità, dovremmo rinunciare al dinamismo a favore della performance. (L'intercettazione, che è il fondamento di comportamenti "dinamici" può essere fatta sia in fase di compilazione che in fase di esecuzione. Nel caso di dispostazione statica o vtable senza una macchina virtuale, si applica solo il tempo di compilazione).

+0

Correlato: è normale (nel contesto di un'applicazione Cocoa/CocoaTouch) che una classe Swift non abbia un antenato Cocoa/NSObject? http://stackoverflow.com/q/24057525/404201 –

2

Non posso rispondere alla tua domanda sull'equivalente "isa" veloce, ma penso di conoscere parte della risposta alla tua domanda di fondo.

Gli osservatori di proprietà sembrano essere i mezzi incorporati per il modello di osservatore. Invece della scoperta runtime di "tipo" (RTTI, what-have-you) è intessuta in modo esplicito.

Da 'La Swift linguaggio di programmazione' Pagina 345:

osservatori Proprietà osservare e rispondere ai cambiamenti di valore di una proprietà . Gli osservatori delle proprietà vengono richiamati ogni volta che il valore di una proprietà è impostato a , anche se il nuovo valore è uguale al valore attuale della proprietà .

È possibile aggiungere osservatori di proprietà a qualsiasi proprietà memorizzata definita, oltre alle proprietà di memorizzazione lazy. È anche possibile aggiungere osservatori di proprietà a qualsiasi proprietà ereditata (memorizzata o calcolata) sostituendo la proprietà all'interno di una sottoclasse.

si ha la possibilità di definire uno o entrambi questi osservatori su una proprietà :

  • willSet è chiamato poco prima che il valore viene memorizzato.
  • didSet viene chiamato immediatamente dopo il nuovo valore memorizzato.

io non sono sicuro di come questo è tutto andando a lavorare fuori, ma mi sono incuriosito.

Affidarsi al tipo di rilevamento in fase di esecuzione sembra essere in contrasto con l'ortodossia di tipo statico forte.

+1

Così gli osservatori di proprietà sono cotti proprio dentro. Utile (e utile sapere). Ma ci sono ancora molte altre cose utili da fare con il pattern di intercettazione. . vediamo se possiamo dare una risposta diretta pure. –

+0

Mi aspetto anche che i devoti di Haskell potrebbero spiegare che le chiusure scritte correttamente sono la strada da percorrere. Mentre spero di scoprire il supporto esplicito per la concorrenza, come i canali e le goroutine. se solo. –

+0

Uno degli usi validi dell'intercettazione del metodo è la capacità di modulare i "requisiti trasversali" secondo il paradigma Aspect Oriented Programming. . I fan di ObjC erano innamorati della sua capacità di farlo a runtime, piuttosto che utilizzare uno strumento di compilazione del tempo. Di fatto non esisteva un framework AOP formale per ObjC in quanto le "materie prime" per l'intercettazione in fase di esecuzione erano abbastanza buone da cavarsela. –