首先我們來看一下場景,如果我們現在想對一個類進行功能的擴充,我們該怎么做?
對於面向對象編程的話,首先會想到繼承,但是繼承有兩個問題:
第一個問題:繼承的前提是這個類可以被繼承,因為在Java中有些類是不允許繼承的,定義成final類,同樣的OC中也是有不可以繼承的類
第二個問題:這個類可以被繼承,但是繼承我們知道是侵入性的,就是我可能只是想實現一個功能,但是繼承之后,子類就會把父類的所有功能(屬性和方法)都繼承了,這個代價太大了。沒必要
所以對於Java中,我們可以使用聚合的方式去實現,
而對於C++的話,直接在定義一個功能類,然后讓這個目標類繼承功能類,因為C++中是可以多繼承的
Java和OC是單繼承的,不允許多繼承
那么在OC中當然我們也可以像Java那種方式去采用聚合處理,但是OC中還有一個更強大的處理方式,那就是類別了,下面來看一下例子:我們現在想給NSString類提供一個校驗郵箱的方法validateEmail,OC中NSString類就是不可以繼承的。
不說了,直接看代碼:
NSString+Extension.h
- //
- // Extension.h
- // 09_ClassTarget
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- //定義類別的文件命名規則:類名+類別名稱,如“NSString+Extension.h"
- @interface NSString (Extension)
- - (BOOL)validateEmail;
- //覆蓋NSString中的intValue方法
- - (NSInteger)intValue;
- @end
NSString+Extension.m
- //
- // Extension.m
- // 09_ClassTarget
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import "NSString+Extension.h"
- @implementation NSString (Extension)
- - (BOOL)validateEmail{
- NSRange range = [self rangeOfString:@"@"];
- if(range.location == NSNotFound){
- return NO;
- }else{
- return YES;
- }
- }
- //這里可以看出,這里是沒辦法調用NSString中得intValue方法,這個和繼承有區別的
- - (NSInteger)intValue{
- NSLog(@"intValue");
- return 0;
- }
- @end
這里我們就定義了一個類目,下面來解釋一下:
類別文件的定義格式:
類別的文件名的格式:"需要添加類別的類名+類別的名稱"
比如這里我們需要對NSString類添加一個類目Extension,那么文件名就是:NSString+Extension.h和NSString+Extension.m
類目的定義格式:
@interface 需要添加類別的類名 (類別名)
....
@end
這個和類定義格式差不多,就是在后面多了一個括號類別名
例如:
@interface NSString (Extension)
....
@end
類別名是可以隨便取的
看到上面的代碼,在NSString+Extension.h中
我們就可以定義validateEmail方法了,同時我們在定義了一個intValue方法
intValue方法是NSString本身就有的,這里就是為了演示一下,如果在添加的類目中重新定義了類中的已有的方法,那么類目中的方法會被覆蓋,和類的繼承差不多,但是這里有一點需要注意,這里是不能使用super關鍵字去調用NSString的intValue方法的,所以intValue覆蓋了NSString類中的intValue方法之后,NSString類中的intValue方法原先的功能就沒有了,這個得注意一下。
看一下測試代碼
main.m
- //
- // main.m
- // 09_ClassTarget
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "NSString+Extension.h"
- //這里只是為了演示如果想擴展一個類的功能,可以通過繼承的方式去實現
- //但是通過繼承來實現這項功能話,有點大材小用的感覺,因為我們只需要一個判斷郵箱的合法性的方法,所以繼承就大了,沒必要
- //但是這里會出錯,因為NSString是不允許繼承的
- //所以這里我們就要用到一個很強大的技術:類目
- //類目的定義和累的定義相似,在.h文件里聲明,.m文件中實現方法
- //類目可以覆蓋方法,但是不會再執行之前的那個方法了,而是調用新的方法
- //類目不能為類添加屬性(實例變量)
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
- NSString *s = @"123456@qq.com";
- BOOL isEmail = [s validateEmail];
- if(isEmail){
- NSLog(@"有效郵箱");
- }else{
- NSLog(@"無效郵箱");
- }
- //調用的是我們類目中的intValue方法
- NSInteger i = [s intValue];
- NSLog(@"intValue is %i",i);
- }
- return 0;
- }
這樣我們就給NSString類添加了一個校驗郵箱的方法,同時類目中的intValue方法也會覆蓋原先類中的intValue方法。
通過這個例子,我們可以看到OC中的類目真的很強大呀!!
而且類目其實還有一個隱藏的用處,從他的字面意思上就知道具有分類的作用,比如一個類中的方法有時候我們可能會需要進行分類(比如:打印分類,比較分類等),這樣代碼看上去也很優雅。我們可以翻看Foundation框架中的NSArray類(這個類我們后面會說到的,和Java中的List差不多):
還有一個類目。
這里我們也了解到了,一個類是可以定義多個類目的。而且類目的作用可以沿襲到子類,就是父類的類目中的方法子類依然可以使用super關鍵字進行調用的。
總結
這一篇文章就介紹了OC中的一個強大功能類目,這個在對以后的擴展性起到至關重要的作用,也算是OC中的一個重點了,后續我們會經常用到這個功能。