类别的实际用途是什么而不是继承?

时间:2012-02-18 17:58:30

标签: objective-c cocoa-touch

我试图了解类别的实际用法,而不是Objective-C中的继承。我什么时候应该选择使用类别?使用代码的真实示例会很有帮助。

6 个答案:

答案 0 :(得分:3)

当您需要向现有类添加功能时。

例如,您的应用正在使用NSDateNSString个实例,并且您想要添加一些功能。您无法将功能添加到子类,因为您无法强制系统方法返回子类。

只需查看API中的示例:

1 / NSDictionary用于保存文件属性,并具有返回文件大小的方法 2 / NSString有一个用绘图扩展它的UI类别。请注意,您不希望可以绘制单独的字符串子类。您希望所有字符串都能够被绘制。

答案 1 :(得分:2)

当我需要添加一些方便的函数时,我会使用类别,我将重复使用这些函数到现有的类,而不需要子类来覆盖该类的某些现有函数。

例如,当我想检查空字符串,或删除字符串的所有前导和尾随空格时:

.h文件:

@interface NSString  (Extension)

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

@end

.m文件:

@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!
       }

答案 2 :(得分:1)

我认为类别是实现继承提供的某些功能的一种更简单的方法。继承不提供其他类别的事项。类别允许您扩展现有类的功能,而无需对其进行子类化。您还可以使用它们来替换类中的现有方法。与指向原始类的后代的子类不同,类别方法有点用螺栓固定到现有类上。一旦将类别方法添加到目标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

使用NSString-encryption.m

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

正如您所看到的,该类别比子类更容易使用。这个方法也可以从NSMutableString调用,因为它继承自NSString。所以它很强大。

您还可以使用category替换类上的现有方法。

类别的另一个用途是它可以用于私有方法,因为目标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  

类别的缺点是,如果需要将成员变量添加到类中,则无法使用它们。

答案 3 :(得分:0)

Sulthan解释得很好。这是通过添加类别来扩展NSString功能的代码example。您可以通过这种方式使用类别来扩展您没有实现的类,而无需对它们进行子类化。

答案 4 :(得分:0)

如果要将添加方法添加到类中,请使用类别。如果要更改类中现有方法的功能,请创建子类。

有点/ sorta可以使用类别来替换现有方法,有点像覆盖子类,但不应该使用类别。原因有三:1)您无法访问原始方法; 2)你不会破坏现有的代码; 3)如果多个类别试图“覆盖”同一个方法,那么该类最终的方法是未定义的。基本上,类最终将使用应用于类的最后一个类别的方法,但不能依赖应用类别的顺序。这是乱七八糟的食谱,所以就是不要这样做。

因此,您可以使用类别向NSData添加方法,例如+(NSData*)dataWithCryptographicallyRandomBytes:(NSUInteger)length-(void)base64Decode。但是如果你想改变现有方法的行为,比如-writeToFile:atomically:,你应该创建一个NSData的子类并在那里实现你的新功能。首先,您可能仍希望使用覆盖中的现有行为,并且子类化允许您通过调用[super writeToFile:file atmoically:YES]来执行此操作。此外,在这里使用子类意味着您的新行为只会影响您自己的代码 - 它不会影响在框架中其他地方使用NSData,而不会期望您的新功能。

答案 5 :(得分:0)

类别类似于Java接口(在java中,实现不是可选的) - 一种对方法进行分组并使对象响应特定API的方法 - 独立于类类型。如果你需要添加额外的ivars并且新类与isa关系匹配(student isa person),则继承是有意义的。添加一些实用程序方法并不是一个例子 - 这通常是通过协议完成的。类别通常与代理一起使用,其中有问题的方法是可选的。