Каково фактическое использование категорий вместо наследования? - PullRequest
0 голосов
/ 18 февраля 2012

Я пытаюсь понять фактическое использование категорий в отличие от наследования в Objective-C. Когда я предпочитаю использовать категорию? Будет полезен реальный пример с кодом.

Ответы [ 6 ]

3 голосов
/ 18 февраля 2012

Когда вам нужно добавить функциональность в существующий класс.

Например, ваше приложение работает с NSDate или NSString экземплярами, и вы хотите добавить некоторые функции. Вы не можете добавить функциональность в подкласс, потому что вы не можете заставить системные методы возвращать подкласс.

Просто посмотрите на примеры в API:

1 / NSDictionary используется для хранения атрибутов файла и имеет метод, который возвращает размер файла.
2 / NSString имеет категорию пользовательского интерфейса, которая расширяет его с помощью рисунка. Обратите внимание, что вам не нужен отдельный подкласс строки, который можно нарисовать. Вы хотите, чтобы все строки имели возможность рисовать.

2 голосов
/ 18 февраля 2012

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

Например, когда я хочу проверить пустую строку или удалить все начальные и конечные пробелы строки:

.h file:

@interface NSString  (Extension)

-(BOOL)isEmptyString;
-(NSString *)trimLeadingAndTrailingWhiteSpaces;

@end

.m file:

@implementation NSString  (Extension)

-(BOOL)isEmptyString
{
    NSString *myString = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    if (myString.length == 0)
        return TRUE;
    else
       return FALSE;
}

-(NSString *)trimLeadingAndTrailingWhiteSpaces
{
    NSString *myString = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    return myString;
}
@end

Для использования:

 someString = [someString trimLeadingAndTrailingWhiteSpaces];

 if ([someString isEmptyString])
       {
         //someString is empty, do whatever!
       }
1 голос
/ 19 февраля 2012

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

Например, если вам нужна функция шифрования, которую необходимо использовать для всех данныхв вашем проекте и говорят, что большинство ваших данных использует только NString для сохранения и манипуляции.Один из способов сделать это - создать категорию для NSString

NSString-Encryption.h

   @interface NSString (Encryption)
     -(NSString*) encrypt;
    @end

NSString-Encryption.m

#import "NSString-Encryption.h"
@implementation NSString (Encryption)
 -(NSString*) encrypt
{ 
 // your encryption method here 
  return encryptedString; 
}
@end

UseNSString-encryption.m

 NSString *testString = @"this is test"; 
 NSString *encryptedString = [testString encrypt];

Как видно, эту категорию проще использовать, чем подкласс.Этот метод может быть вызван из NSMutableString также, поскольку он наследуется от NSString.Так что это мощно.

Вы также можете использовать категорию для замены существующих методов в классах.

Другое использование категории заключается в том, что она может использоваться для частных методов , поскольку цель c не имеет формального частного обозначения для методов.Это делается путем помещения категории в файл .m вместо файла .h.

Phone.h

@interface Phone:NSObject
 -(void) call; 
 @end 

Phone.m

   @interface Phone(Private)
       -(void) validatePhoneEntry:(NSString*) phoneNumber; 
     @end 

     @implementation Phone 

     -(void) validatePhoneEntry:(NSString*) phoneNumber
     {

     } 

     -(void) call
     {
     }

     @end  

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

0 голосов
/ 19 февраля 2012

Категории похожи на интерфейсы Java (в java реализация не является обязательной) - способ группировать методы и заставлять объекты реагировать на определенный API - независимо от типа класса.Наследование имеет смысл, если вам нужно добавить дополнительные ivars, и новый класс соответствует отношению isa (студент isa person).Добавление нескольких служебных методов не создает изюминку - обычно это делается с помощью протоколов.Категории часто используются с делегатами, где указанные методы являются необязательными.

0 голосов
/ 19 февраля 2012

Если вы хотите добавить методы в класс, используйте категорию.Если вы хотите изменить функциональность существующих методов в классе, создайте подкласс.

Возможно использовать категорию для замены существующего метода, что-то вроде переопределения вподкласс, но вы не должны использовать категории для этого.Есть три причины: 1) вы теряете доступ к оригинальному методу;2) вы не сломаете существующий код;3) если более одной категории пытается «переопределить» один и тот же метод, метод, с которым будет работать класс, не определен.По сути, класс получит метод из последней категории, примененной к классу, но нельзя полагаться на порядок, в котором применяются категории.Это рецепт беспорядка, так что просто не делайте этого.

Итак, вы можете использовать категорию для добавления методов к NSData, таких как +(NSData*)dataWithCryptographicallyRandomBytes:(NSUInteger)length или -(void)base64Decode.Но если вы хотите изменить поведение существующего метода, такого как -writeToFile:atomically:, вы должны создать подкласс NSData и реализовать там свою новую функциональность.Во-первых, вы все еще можете использовать существующее поведение в вашем переопределении, и подклассы позволяют вам сделать это, вызвав [super writeToFile:file atmoically:YES].Кроме того, использование здесь подкласса означает, что ваше новое поведение будет влиять только на ваш собственный код - это не повлияет на использование NSData в других частях инфраструктуры, которые могут не ожидать ваших новых функций.

0 голосов
/ 18 февраля 2012

Султан хорошо это объясняет.Вот код пример расширения функциональности NSString путем добавления категории.Вы можете использовать категории таким образом, чтобы расширять классы, для которых у вас нет реализаций, без их подкласса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...