2015-07-01 4 views
5

So habe ich eine Kategorie auf NSObject CustomCategory genannt, wie folgend:Kategorie auf NSObject funktioniert auch auf Klasse

#import <Foundation/Foundation.h> 

@interface NSObject (CustomCategory) 

-(BOOL)doSomething; 

@end 

#import "NSObject+CustomCategory.h" 

@implementation NSObject (CustomCategory) 

-(BOOL)doSomething 
{ 
    NSLog(@"Done"); 
    return NO; 
} 

@end 

Idealerweise diese auf ein Objekt wie dies funktionieren wird:

NSObject* object = [NSObject new]; 
[object doSomething]; 

jedoch ich fand, dass es auch ohne Probleme auf diese Weise funktioniert:

[NSObject doSomething]; 

So frage ich mich, da es eine Instanzmethode ist Ich habe über die Kategorie hinzugefügt, warum es auch an einer Klasse funktioniert?

+1

Zeigen Sie den Deklarations- und Definitionscode der Kategorie an. – zaph

+0

durch die Arbeit Sie meinen, dass es kompiliert oder dass es den Code innerhalb DoSomething –

+0

Alle Klassen sind auch NSObjects (außer vielleicht NSProxy). – user3125367

Antwort

3

Instanzmethoden für NSObject sind auch Klassenmethoden für NSObject.

Dies funktioniert aufgrund der Art und Weise, wie Objective-C dynamisch versendet. Wenn Sie eine Nachricht an ein beliebiges Objekt senden, wird die Methodenimplementierung in der Objektklasse nachgeschlagen. Wenn Sie eine Nachricht an eine Klasse senden, senden Sie eine reguläre Nachricht an das Klassenobjekt. Dort wird die Implementierung in der sogenannten Meta-Klasse nachgeschlagen. Die Metaklassen werden vom Compiler automatisch generiert. Klassenmethoden sind nur Instanzmethoden der Meta-Klasse. Dies wird vom Compiler transparent gehandhabt.

Vererbung funktioniert auch auf der Meta-Klassenebene. Also erbt die Meta-Klasse für eine Klasse von der Meta-Klasse ihrer Oberklasse. Wir haben dort zwei parallele Vererbungshierarchien. Nur Stammklassen wie NSObject werden unterschiedlich behandelt. Dort kann die Meta-Klasse nicht von der Meta-Klasse der Superklasse erben, da es keine Superklasse gibt. Bei Root-Klassen erbt die Meta-Klasse von der Root-Klasse selbst.

Und da Klassenmethoden einer Klasse Instanzmethoden ihrer Meta-Klasse sind und NSObjects Meta-Klasse von NSObject selbst erbt, sind Instanzmethoden für NSObject auch Klassenmethoden für NSObject.

+1

s/NSObject/Root-Klasse/g. Es gibt andere Stammklassen wie NSAtom, NSProxy usw. –

+0

NSObject Metaklasse ist nicht NSObject. Es ist definitiv getrennt. –

+0

Ja, das ist behoben. Es ist nicht NSObject, es erbt von NSObject. Sonst könnten Wurzelklassen überhaupt keine Klassenmethoden haben. – Sven

-2

Alle Class in Objective C ist intern ein Objekt, was bedeutet, dass es eine Unterklasse von NSObject ist.

+0

Nicht ganz. Meta-Klassen erben NICHT alle von 'NSObject', noch sind sie Instanzen von' NSObject'. Sie werden während der Methodenauflösung tatsächlich vollständig getrennt behandelt, um Root-Objekt-Fälle zu behandeln. –

+0

Wahr, jede Klasse ist ein Objekt. Aber die Klassenobjektklasse ist nicht automatisch NSObject. @ RichardJ.RossIII: Meta-Klassen für jede Klasse, die von NSObject erbt auch von NSObject erben. Root-Klassen sind ihre eigene Meta-Klasse. – Sven

+1

@Sven, aber es ist keine Instanz von 'NSObject', was diese Antwort irreführend macht. Die wahre Antwort ist, dass die Methodenauflösung für Stammklassen getrennt behandelt wird. –

3

Für Bezug auf jemand für die tatsächliche Lage dieses in der Runtime-Quelle suchen, sie wohnt derzeit in objc-runtime-new.mm ‚s methodizeClass Funktion:

... snip... 

// Root classes get bonus method implementations if they don't have 
// them already. These apply before category replacements. 

if (cls->isRootMetaclass()) { 
    // root metaclass 
    addMethod(cls, SEL_initialize, (IMP)&objc_noop_imp, "", NO); 
} 

... snip ... 

... Und die +initialize Methode einer Meta-Klasse Fügen Sie alle Methodenimplementierungen aus ihrer Instanz hinzu und konvertieren Sie sie in eine Klassenmethode.

Und im Gegensatz zu dem, was @Sven gesagt hat, ist NSObjects Meta-Klasse nicht eigentlich NSObject. Eine Klasse hat in der Laufzeit immer eine eigene Metaklasse, unabhängig davon, ob sie root ist oder nicht.

+0

Ihr Snippet sagt nichts, es zeigt, woher + initialize von den Wurzelmetaklassen herkommt. Ich gebe zu, ich war ein bisschen ungenau, ich habe gerade nachgesehen. Die Metaklasse von NSObject ist nicht NSObject, sie erbt direkt von NSObject. Jedes Objekt hat eine Klasse und jede Klasse muss eine Oberklasse haben und dort die parallelen Vererbungshierarchien kombinieren. – Sven

Verwandte Themen