2013-06-17 9 views
6

C'è un modo per rilevare dinamicamente dall'interno di una classe figlio se ha la precedenza sui metodi dei genitori?Objective-C rileva se la classe sovrascrive il metodo ereditato

Class A { 
    - methodRed; 
    - methodGreen; 
    - methodBlue; 
} 
Class B inherits A { 
    - methodRed; 
} 

Dal suddetto esempio vorrei sapere se la classe B è in grado di rilevare in modo dinamico che solo -methodRed; stata ignorata.

La ragione mi chiedo di questo approccio rispetto ad alcune altre possibilità è perché ho decine di visualizzazioni personalizzate che cambieranno l'aspetto. Sarebbe molto meno codice se potessi rilevare dinamicamente i metodi sovrascritti rispetto a tenere traccia.

risposta

16

Questo è abbastanza semplice da testare:

if (method_getImplementation(class_getInstanceMethod(A, @selector(methodRed))) == 
    method_getImplementation(class_getInstanceMethod(B, @selector(methodRed)))) 
{ 
    // B does not override 
} 
else 
{ 
    // B overrides 
} 

devo chiedersi come sapere se B sovrascrive un metodo su A è utile, ma se volete sapere, questo è come si scopre.

Vale anche la pena notare: Nei termini più stringenti il ​​codice precedente determina se l'implementazione per il selettore su B è diversa dall'implementazione del selettore su A. Se si avesse una gerarchia come A> X> B e X sovrascrive il selettore, questo segnalerebbe comunque diverse implementazioni tra A e B, anche se B non era la classe dominante. Se si vuole sapere in particolare "fa B Override questo selettore (indipendentemente dal qualsiasi altra cosa)" che si vorrebbe fare:

if (method_getImplementation(class_getInstanceMethod(B, @selector(methodRed))) == 
    method_getImplementation(class_getInstanceMethod(class_getSuperclass(B), @selector(methodRed)))) 
{ 
    // B does not override 
} 
else 
{ 
    // B overrides 
} 

Questo, forse, ovviamente, pone la domanda "fa B hanno una diversa implementazione per il selettore rispetto alla sua superclasse "che è (forse più specificamente) ciò che hai chiesto.

+0

Grazie per l'aggiornamento, questo è buono! Ti darei un altro voto, ma te ne ho già dato uno. – cnotethegr8

+2

chiunque usi questo codice dovrebbe '#importare ' – cnotethegr8

+1

Ancora più semplice: 'class_getMethodImplementation()' può sostituire le due chiamate concatenate in precedenza e in alcuni casi potrebbe essere più veloce. Vedi https://developer.apple.com/documentation/cocoa/reference/objcruntimeref per i dettagli. –

11

All'interno della vostra classe di base:

BOOL isMethodXOverridden = [self methodForSelector:@selector(methodX)] != 
          [BaseClass instanceMethodForSelector:@selector(methodX)]; 

vi darà YES se methodX viene sovrascritto dal sottoclasse.

Le risposte sopra sono anche corrette, ma potrebbero sembrare migliori.