2015-07-01 2 views
5

Так что есть категория на NSObject называется CustomCategory, следующим образом:Категория на NSObject также работает по классу

#import <Foundation/Foundation.h> 

@interface NSObject (CustomCategory) 

-(BOOL)doSomething; 

@end 

#import "NSObject+CustomCategory.h" 

@implementation NSObject (CustomCategory) 

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

@end 

В идеале, это будет работать на объекте, как это:

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

Однако, Я обнаружил, что он также работает таким образом без проблем:

[NSObject doSomething]; 

Так что я интересно, так как это метод экземпляра Я добавил через категорию, почему он также работает на классе?

+1

Показать объявление и код определения категории. – zaph

+0

, работая, вы имеете в виду, что он компилирует или выполняет код внутри doSomething. –

+0

Все классы также являются объектами NSObject (кроме, возможно, NSProxy). – user3125367

ответ

3

Методы экземпляров в NSObject также являются методами класса в NSObject.

Это работает из-за того, как Objective-C выполняет динамическую отправку. Если вы отправляете сообщение любому объекту, реализация метода просматривается в классе объектов. Если вы отправляете сообщение классу, вы отправляете регулярное сообщение объекту класса. Там реализация просматривается в так называемом метаклассе. Мета-классы автоматически генерируются компилятором. Методы класса - это только методы экземпляра метакласса. Компилятор обрабатывается прозрачно.

Наследование также работает на уровне метакласса. Таким образом, метакласс для класса наследуется от метакласса его суперкласса. У нас есть две параллельные иерархии наследования. Только корневые классы, такие как NSObject, обрабатываются по-разному. Там метакласс не может наследовать от метакласса суперкласса, так как нет суперкласса. Для корневых классов мета-класс наследуется от самого корневого класса.

И поскольку методы класса класса являются методами экземпляра метакласса метакласса и метаклассами NSObjects, которые наследуются от самих методов экземпляра NSObject в NSObject, также являются методами класса в NSObject.

+1

s/NSObject/Root Class/g. Существуют и другие корневые классы, такие как NSAtom, NSProxy и т. Д. –

+0

Мета-класс NSObject IS NOT NSObject. Это определенно раздельно. –

+0

Да, исправлено это. Это не NSObject, он наследуется от NSObject. В противном случае корневые классы вообще не могли бы иметь методы класса. – Sven

-2

Каждый объект Class Объектив C является внутренним объектом, что означает, что это подкласс NSObject.

+0

Не совсем. Мета-классы НЕ все наследуют от 'NSObject', и не являются экземплярами' NSObject'. На самом деле они обрабатываются полностью отдельно во время разрешения метода для обработки случаев корневых объектов. –

+0

Правда, каждый класс является объектом. Но класс объектов класса не является автоматически NSObject. @ RichardJ.RossIII: Мета-классы для любого класса, который наследует от NSObject, также наследуются от NSObject. Корневые классы - это их собственный метакласс. – Sven

+1

@Sven, но это не экземпляр 'NSObject', который делает этот ответ вводящим в заблуждение. Истинный ответ заключается в том, что разрешение метода обрабатывается отдельно для корневых классов в устаревших целях. –

3

Для ссылки на тех, кто ищет фактического расположения этого в источнике выполнения, в настоящее время он находится в objc-runtime-new.mm «s methodizeClass функции:

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

... И +initialize метод мета-класс добавить все реализации метода из своего экземпляра и преобразовать их в метод класса.

И, вопреки тому, что сказал @Sven, метаклассом NSObject на самом деле не является NSObject. Класс всегда имеет отдельный мета-класс во время выполнения, независимо от того, является он корнем или нет.

+0

Ваш фрагмент ничего не говорит, он показывает, откуда и откуда инициализируется исходный метаклассы. Я признаю, я был немного неточен, я только что проверил. Метакласс класса NSObject не является NSObject, он наследуется непосредственно из NSObject. Каждый объект имеет класс, и каждый класс должен иметь суперкласс и там объединяются иерархии параллельного наследования. – Sven

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