OC中的類分兩個文件,.h用來聲明類的變量和函數,.m文件負責實現,與.h配合使用。
OC中最根本的類叫NSObject,OC是單繼承的。
聲明類以@interface開頭,以@end結尾,實現類用@implementation開頭,以@end結尾。
繼承用冒號。
OC當中使用一個類時,導包就是#import一個類的頭文件。
聲明類時,成員變量要聲明在大括號中,方法聲明在大括號外,如果是對象方法要寫-號,靜態方法要寫+號,所有在.h文件當中聲明的方法都是公共方法,凡是類型,都要寫括號,在方法名后,一個參數要一個括號,如:
//Student.h#import <Foundation/Foundation.h>@interface Student : NSObject { int age;}-(int)getAge;-(void)setAge:(int)age;@end實現類時,首先要導入.h的聲明.//Student.m#import "Student.h"@implementation Student- (int)getAge { return age;}- (void)setAge:(int)newAge { age = newAge;}@end2、對象的創建
對象的創建需要調用類的靜態方法alloc分配內存。
調用靜態方法要寫[],里面是類名和方法名,返回值需要用指針來接收,也就是說,OC中的對象都要寫個*。比如這句話調用了Student的一個靜態方法alloc分配內存,并返回了一個指針來接收,其實alloc方法返回的是id類型,可以暫時理解為任何類型:
Student *stu = [Student alloc];分配內存后要調用一個動態方法進行初始化,相當于stu指針給Student發送了一個init消息:
stu = [stu init];也就是說定義一個變量需要兩句話,但是很麻煩,所以可以連起來寫,這種方法最常用:
Student *stu = [[Student alloc] init];3、定義有多個參數的方法
- (void)setAge:(int)newAge andNo:(int)newNo{ age = newAge; no = newNo;}調用:
[stu setAge:100 andNo:1];
也就是說方法名可以拆成多個部分。
注意,這里的方法的方法名是setAge:andNo:,冒號也是方法名的一部分,代表有輸入參數。在使用@selector(method)時要注意加上冒號。
4、set / get屬性支持點語法
OC中的get方法不推薦使用get前綴,都是直接寫變量名,比如[stu age];。
OC也支持點語法,比如:person.age = 10;
不過這句話并不是java那樣給成員變量賦值,而是調用了對應的set方法,在編譯的時候會自動轉化為方括號的語法。
如果點語法在等號左邊,則調用set方法,在右邊則調用get方法。為了和成員變量加以區分,OC推薦成員變量都以 _ 開頭。
在set方法當中,絕對不能調用self.age=newAge,根據上面的解釋,這種寫法會死循環。同樣在get方法里也不能return self.age。在OC當中用點語法來表示get/set方法。
5、OC屬性機制
在.h 文件中做屬性聲明:
#import <Foundation/Foundation.h>@interface Student : NSObject { int _age;}@PRoperty int age;@end當編譯器遇到原型關鍵字時,會自動把這行代碼展開成get和set方法的“聲明”,并自動生成一個“同名”的“私有”的成員變量,通常習慣把成員變量定義成_age。
如果我們手動實現了get或set方法,那么就不會生成對應的方法了。
6、@class 關鍵字
如果一個類持有另一個類,而且在.h文件里使用#import "Book.h"導入的話,會把.h全拷過去,性能會受影響,而且getset等方法也會暴露出去,一般不這么寫,習慣在.h文件里使用關鍵字:@class Book;,只要知道Book是個類就可以了,在.m文件里真正要用到類里的方法時,再使用#import "Book.h"來獲取其中的方法。一個典型的錯誤就是A類improt了B類,B也improt了A類,這樣就會死循環而報錯。而且,如果有多個文件同時improt了一個頭文件,那么一旦這個頭文件發生了改變,其他引用它的文件都要重新編譯,而@class不存在這個問題。
需要注意的是,如果是繼承某個類,就一定要improt頭文件,因為這樣才能知道它里面定義了什么方法。如果只是定義成員變量或屬性,就@class。
7、Category(分類)
Category(分類)可以動態地給已經存在的類添加方法,類似C#的擴展方法。需要新建一個文件,類型是OCcategory,在Category on當中選擇目標類,會生成“類名+分類名”.h和.m兩個文件,生成的類名右邊括號里就是分類名。需要注意的是這個類的.h文件里必須import原始類,不能@class,原因是要知道原先類里有什么方法。
#import "Student.h"@interface Student (Test)-(void)test2;@end#import "Student+Test.h"@implementation Student (Test)-(void)test2{ NSLog(@"調用了test2方法");}@end#import <Foundation/Foundation.h>#import "Student.h"#import "Student+Test.h"int main(int argc, const char * argv[]){ @autoreleasepool { Student *stu = [Student student]; [stu test2]; } return 0;}8、Protocol(協議)
協議的聲明看起來比較類似于Java中一個類的接口,但是和接口不同的是:協議沒有父類也不能定義實例變量。
協議是一種特殊的程序設計結構,用于聲明專門被別的類實現的方法。
協議在以下場合非常有用:
1、需要由別的類實現的方法
2、聲明未知類的接口
3、兩個類之間的通信 協議的基本特點
協議特點:
1、協議可以被任何類實現的方法
2、協議本身不是類,它是定義了一個其他類可以實現的接口
3、類別也可以采用協議(用的不多) 協議中的關鍵字
協議關鍵字:
1、@required:表示必須強制實現的方法
2、@optional:表示可以有選擇性的實現方法
范例:
123456789101112131415 | //協議的聲明#import <foundation foundation.h="">@protocol OneProtocol <nsobject> //可以選擇實現的方法:@optional-(void) optionalMethod1;-(void) optionalMethod2;//必須實現的方法:@required-(void) requiredMethod1;@end//采用協議(Test.h)#import "OneProtocol.h"@interface Test : NSObject<oneprotocol></oneprotocol></nsobject></foundation> |
1234567891011121314 | #import "Test.h" @implementation Test -(void)optionalMethod1{ //可選擇實現方法1}-(void)optionalMethod2{ //可選擇實現方法2}-(void)requiredMethod1{ //必須是實現方法2}@end |
12345 | Test *test=[[Test alloc]init]; [test optionalMethod1]; [test optionalMethod2]; [test requiredMethod1]; [test autorelease]; |
int (^Sum)(int,int) = ^(int a, int b) { return a + b;}; int a = Sum(10,11);在block里是可以使用花括號外的變量的,但是不能修改它,類似java在外部加一個final,除非加一個關鍵字__block就能改變了,比如:
void test() { __block int c = 1; int (^Sum)(int,int) = ^(int a, int b) { c = 10; return a + b + c; }; NSLog(@"%i", Sum(1,2));}另外可以提前聲明block的類型:
typedef int (^MySum) (int,int);這樣就可以用這個類型來定義block了:
MySum sum = ^(int a, int b) { return a+b; };
新聞熱點
疑難解答