antonio's blog

antonio's blog


Блог о всяком разном, связанном с разработкой ПО. Пишу редко, когда есть время и желание.

Anton Dobkin
Author

Share


Tags


Категории в Objective-C

Anton DobkinAnton Dobkin

Категории в Objective-C - это механизм позволяющий расширять существующие классы. Используя категории к классу можно добавить новые методы без применения наследованная и не имея исходников изменяемого класса. Добавляемые таким способом методы становятся доступными всем классам, унаследованным от изменяемого. С помощью категорий также можно переопределять существующие методы. Категория имеет доступ к переменным экземпляра исходно класса, однако с помощью категорий невозможно добавить новые переменные экземпляра.

Объявление категории похоже на объявление класса:

@interface NSString (MyCategory)
-(void) myMethod;
@end

Описание категории начинается с директивы @interface, после которой следует имя расширяемого класса, в примере это NSString. Затем в круглых скобках (...) указывается название категории. После этого описываются добавляемые в класс методы. Описание категории заканчивается директивой @end

К классу можно добавить любое кол-во категорий, но они должны иметь уникальные имена.

Реализация категории также похожа на реализацию класса и не вызывает сложностей:

@implementation NSString (MyProperty)

-(void) myMethod {
// тело метода
}

@end

Реализация категории начинается с директивы @implementation, после которой следует имя расширяемого класса и название категории, заданное в круглых скобках. После этого идет реализация добавляемых методов. Реализация категории заканчивается директивой @end

Категории можно использовать для того, чтобы обеспечить реализацию классом каких-либо протоколов.

@protocol MyProtocol
-(void) myMethod;
@end

@interface NSString (MyCategory) <MyProtocol>

@end

@implementation NSString (MyCategory)
-(void) myMethod {
// Реализация метода
}
@end

Здесь мы говорим, что класс NSString принимает протокол MyProtocol и реализует его обязательный метод myMethod

Категории можно использовать для раннего объявления методов, а также для раскрытия приватных методов. Допустим у вас имеется класс MyTestClass с приватным методом privateMetod:

// Описание класса, h - файл
@interface MyTestClass: NSObject
-(void) publicMethod;
@end

// Реализация класса, m - файл
@interface MyTestClass()
-(void) _privateMethod;
@end

@implementation MyTestClass
-(void)publicMethod {
...
}

-(void) _privateMethod {
...
}
@end

Если из другого класса вы обратитесь к методу privateMetod, то получите сообщение об ошибке во время компиляции:

No visible @interface for 'MyTestClass' declares the selector 'privateMethod'  

Для предотвращения этого можно воспользоваться категорией. В файле реализации класса, в котором вы обращаетесь к приватному методу класса MyTestClass, опишите категорию:

@interface MyTestClass (PrivateMetod)
-(void)_privateMetod;
@end

и вы больше не получите сообщение об ошибке во время компиляции. При этом мы только описали категорию, но не реализовали ее.

Неформальные протоколы

Методы описанные в категории необязательны для реализации. Категория с описанными, но не реализованными методами называется неформальным протоколом. Неформальные протоколы часто определяются для корневого класса NSObject, при этом они не имею реализации в самом классе. Каждый подкласс будет отвечать на сообщения описанные в категории, но при этом будут делать что-то полезное только реализованные методы. Методы, по мере необходимости, могут быть реализованы в подклассах, при этом реализуемые методы должны быть объявлены в секции @interface.

Anton Dobkin
Author

Anton Dobkin

Comments