在今天的教程里,我们将会学习到类别,以及如何使用类别来扩展Cocoa-Touch类的功能。这是我们学习Objective-C系列的最后一章了,就让我们也会回顾一下目前所学到的知识,还有,探讨一下日后开发Objective-C或iphone应用程序的一些技巧。
那么,什么是类别呢?大量的Objective-C系列教程会忽略掉类别,这是一个非常有用的语言功能。通过消除不必要的子类,类别有助于保持代码的清洁。从我们已经了解到的,如果我们有一个NSString对象,然后要添加一些函数去做一些事情,例如添加一个可以把字符串中’a’替换成’4’,这样我们可以继承NSString并且添加自己的方法。当我们创建了Car类,我们也可以看到这子类。之前我过叫大家在这教程的最后,创建这样的一个Car子类,所以你可以在基类添加函数了,但在某些情况下,类别提供一个很好的方法去为一个类添加额外的方法:
类别允许我们为一存在的类添加方法,这样,我们程序中所有类的实例可以获得这样的功能了。例如,我们有100个NSString对象在应用程序里,但你想拥有一个自定义子类,所以每个NSString就得拥有一个额外的方法了(例如reverseString)。有了类别,我们可以轻松地把方法加进类别里,并且所有的实例会允许被使用新方法。语法是和子类的很不相同的,并且类别不会允许你去使用实例变量。然而,方法重写是允许的,但这要慎用,不到万不得已之时勿用。
类别的语法形式和类相似,他们中也分别有一个接口和一个实现。接口看起来是这样的:
1: @interface ClassNameHere (category)
2:
3: // method declaration(s)
4:
5: @end
6:
7: The implementation looks like this;
8:
9: @implementation ClassNameHere (category)
10:
11: // method implementation(s)
12:
13: @end
很简单对吧?好吧,让我们看看一个例子吧。我们将要创建一个用来实现string反转的方法。虽然这方法没多大实际用处,但用来做什么并不是重点。你应该已经知道接口的形式了,但这已经存在的了:
1: @interface NSString (reverse)
2:
3: -(NSString *) reverseString;
4:
5: @end
那怎样创建实现呢?
1: @implementation NSString (reverse)
2:
3: -(NSString *)reverseString {
4:
5: }
6:
7: @end
接下来,我们将需要添加一些代码来让string反转。由于我们将为NSString类添加方法,我们得自我引用字符串了。现在,为了反转字符串,我们需要一个新的临时字符串对象。我们会用一个循环去反转这字符串,每次寻找一个字符添加到反转字符对象上。代码如下:
1: int length = [self length];
2: NSMutableString *reversedString;
3:
4: reversedString = [[NSMutableString alloc] initWithCapacity: length];
5:
6: while (length > 0) {
7: [reversedString appendString:[NSString stringWithFormat:@"%C", [self characterAtIndex:--length]]];
8: }
9:
10: return [reversedString autorelease];
这种方法是相当简单的,我们通过每次循环反转字符串中的字符。我们追加使用stringWithFormat和字符标识符。当我们调用这方法,不仅返回长度整数,并且从字符串删除它,循环是沿着字符串进行的哟。
如果是顺利的话,所有的NSString已经在我们项目中了,现在你可以知道为什么类别这么好用吧。
好了,现在我们的 NSString对象都应该有reverseString方法了,回顾一下吧,我们的代码是这样的:
1: @interface NSString (reverse)
2:
3: -(NSString *) reverseString;
4:
5: @end
6:
7: @implementation NSString (reverse)
8:
9: -(NSString *)reverseString {
10: int length = [self length];
11: NSMutableString *reversedString;
12:
13: reversedString = [[NSMutableString alloc] initWithCapacity: length];
14:
15: while (length > 0) {
16: [reversedString appendString:[NSString stringWithFormat:@"%C", [self characterAtIndex:--length]]];
17: }
18:
19: return [reversedString autorelease];
20: }
21:
22: @end
每个代码块(接口和实现)都会在它们自己约定好的文件里。然而,我们命名类别有点不同。我们创建了两个文件:NSString + reverse.h(接口)和NSString + reverse.m(实现)。
这是一个典型的命名规范,我们在这类里加入一个类别。在我们继续之前,还要记得在项目里引入我们的头文件。所以,你现在的代码看起来会像:
1: NSString* testString = @"Just a test";
2:
3: [testString reverseString];
4:
5: NSLog(@"Reversed: '%@'", testString);
如果一切按计划进行,这样控制台会输出”Just a test”。
如果并没有全按照计划进行,检查一下来确保你复制的代码是正确的,并且类别已经引入了头文件(*.h)文件。
看到了吧,类别真的是挺有用的(特别是对于字符串)。在任何项目中都有广泛的应用,通常我会用在检验上。通过这种方法,我可以保证不用任何复杂子类的情况下只在一个地方验证。
今天的结束将代码本系列教程的结束了,回顾以上几个章节,我们提及到的主题如下:
我希望您喜欢这个系列,目前如果你只读了本系列中的一两章,那么我建议您从第一天开始读完。在这系列结束之时,你会有足够的信心在你的应用程序中敲代码。
如果您对本系列有疑问,或者如果您想在Objective-C的另一方面知识开辟一系列教程,请承受时发表评论。
如果你对Objective-C知识有疑问,无论在项目中,或是工作上,请不要犹豫与我联系,可以通过Twitter或是浏览我主页。
本教程暂告一段落了,前面的挑战也将结束。我强烈建议您动起手来建立您的第一个应用程序。提出一个想法和设计方案,用上所有您在本教程系列中学过的知识,好吧,动手吧!
谢谢您的阅读!
系列教程导航
<<学习Objective-C--第五天