第一个OC的类
來源:http://www.cnblogs.com/mjios/archive/2013/04/06/3002814.html
本文目錄- 一、語法簡介
- 二、用Xcode創(chuàng)建第一個(gè)OC的類
- 三、第一個(gè)類的代碼解析
- 四、添加成員變量
- 五、添加方法
- 六、跟Java的比較
- 七、創(chuàng)建對象
- 八、訪問公共成員變量和方法
說明:這個(gè)Objective-C專題,是學(xué)習(xí)iOS開發(fā)的前奏,也為了讓有面向?qū)ο笳Z言開發(fā)經(jīng)驗(yàn)的程序員,能夠快速上手Objective-C。如果你還沒有編程經(jīng)驗(yàn),或者對Objective-C、iOS開發(fā)不感興趣,請忽略。學(xué)習(xí)本專題之前,建議先學(xué)習(xí)C語言專題。
OC是一門面向?qū)ο蟮恼Z言,因此它也有類、對象、靜態(tài)\動(dòng)態(tài)方法、成員變量的概念。這講就來創(chuàng)建第一個(gè)OC的類。
回到頂部一、語法簡介
1.類
在Java中,我們用1個(gè).java文件就可以描述清楚一個(gè)類;在OC中,一般用2個(gè)文件來描述一個(gè)類:
1>?.h:類的聲明文件,用于聲明成員變量、方法。類的聲明使用關(guān)鍵字@interface和@end。
注意:.h中的方法只是做一個(gè)聲明,并不對方法進(jìn)行實(shí)現(xiàn)。也就是說,只是說明一下方法名、方法的返回值類型、方法接收的參數(shù)類型而已,并不會(huì)編寫方法內(nèi)部的代碼。
2>?.m:類的實(shí)現(xiàn)文件,用于實(shí)現(xiàn).h中聲明的方法。類的實(shí)現(xiàn)使用關(guān)鍵字@implementation和@end。
?
2.方法
1> 方法的聲明和實(shí)現(xiàn),都必須以?+?或者?-?開頭
- +?表示類方法(靜態(tài)方法)
- -?表示對象方法(動(dòng)態(tài)方法)
2>?在.h中聲明的所有方法作用域都是public類型,不能更改
?
3.成員變量
成員變量的常用作用域有3種:
1> @public?全局都可以訪問
2> @protected?只能在類內(nèi)部和子類中訪問
3> @private?只能在類內(nèi)部訪問
比Java少了一種作用域:包權(quán)限作用域,原因很明顯:OC沒有包名的概念。
?
回到頂部二、用Xcode創(chuàng)建第一個(gè)OC的類
?1.右擊項(xiàng)目文件夾或者文件,選擇"New File"
?
2.選擇Cocoa的"Objective-C class"
?
3.輸入類名和選擇父類
這里的類名為Student,父類是NSobject
?
4.創(chuàng)建完畢后,項(xiàng)目中多了兩個(gè)文件
* Student.h是類的聲明文件,Student.m是類的實(shí)現(xiàn)文件
* 默認(rèn)情況下,這2個(gè)文件的文件名跟類名一致
* 編譯器只會(huì)編譯.m文件,并不會(huì)編譯.h文件
?
回到頂部三、第一個(gè)類的代碼解析
1.Student.h - 類的聲明文件
1 #import <Foundation/Foundation.h> 2 3 @interface Student : NSObject 4 5 @end1> 看第3行,OC中使用關(guān)鍵字@interface來聲明一個(gè)類,@interface后面緊跟著類名Student。
2> 類名Student后面的冒號(hào)":"表示繼承,即第3行代碼的意思是Student繼承自NSObject。
3> 因?yàn)镹SObject被聲明在Foundation.h中,所以在第1行用#import包含了Foundation.h文件。
4> 第5行的@end表示類的聲明結(jié)束了。@interface和@end是配套使用的。
?
2.Student.m - 類的實(shí)現(xiàn)文件
1 #import "Student.h" 2 3 @implementation Student 4 5 @end1> 看第3行,OC中使用關(guān)鍵字@implementation來實(shí)現(xiàn)一個(gè)類。@implementation后面緊跟的類名,表示究竟要實(shí)現(xiàn)哪一個(gè)類。
2> 因?yàn)镾tudent這個(gè)類是聲明在Student.h中的,所以在第1行用#import包含了Student.h文件。如果你不包含Student.h,第3行代碼肯定報(bào)錯(cuò),因?yàn)樗静恢繱tudent是個(gè)什么鬼東西。
3> 第5行的@end表示類的實(shí)現(xiàn)結(jié)束了。@implementation和@end是配套使用的。
?
回到頂部四、添加成員變量
正常情況下,我們都是把成員變量定義在頭文件中,也就是類的聲明文件(.h)中
1.給Student添加一個(gè)成員變量
1 #import <Foundation/Foundation.h> 2 3 @interface Student : NSObject { 4 int age; // 年齡 5 } 6 7 @end1> 第4行定義了一個(gè)int類型的成員變量age,age的默認(rèn)作用域是@protected,即可以在Student類內(nèi)部和子類中訪問
2> 成員變量必須寫在大括號(hào){ }里面
?
2.設(shè)置成員變量的作用域
接下來給Student增加幾個(gè)不同作用域的成員變量
1 #import <Foundation/Foundation.h> 2 3 @interface Student : NSObject { 4 int age; // 年齡 5 6 @public 7 int no; // 學(xué)號(hào) 8 int score; // 成績 9 10 @protected 11 float height; // 身高 12 13 @private 14 float weight; // 體重 15 } 16 17 @end一共有5個(gè)成員變量,其中
@public作用域的有:no、score
@protected作用域的有:age、height
@private作用域的有:weight
?
回到頂部五、添加方法
前面我們定義了一個(gè)成員變量age,它的作用域是@protected,外界不能直接訪問它。為了保證面向?qū)ο髷?shù)據(jù)的封裝性,我們可以提供age的get方法和set方法,讓外界間接訪問age。接下來在Student中添加age的get方法和set方法。
1.在Student.h中聲明方法
1 #import <Foundation/Foundation.h> 2 3 @interface Student : NSObject { 4 int age; // 年齡 5 6 @public 7 int no; // 學(xué)號(hào) 8 int score; // 成績 9 10 @protected 11 float height; // 身高 12 13 @private 14 float weight; // 體重 15 } 16 17 // age的get方法 18 - (int)age; 19 20 // age的set方法 21 - (void)setAge:(int)newAge; 22 23 @end1> 第18行聲明了age的get方法,方法名就叫做age,OC建議get方法的名字跟成員變量保持一致(如果是在Java中,就應(yīng)該叫做getAge)
2> 第18行最面的?-?表示這是一個(gè)動(dòng)態(tài)方法(?+?則表示靜態(tài)方法)。age前面的(int)表示方法的返回值為int類型,方法的返回值和參數(shù)類型都需要用小括號(hào)()包住
3> 第21行聲明了age的set方法,前面的?-?表示動(dòng)態(tài)方法,(void)表示方法沒有返回值
4> 在OC方法中,一個(gè)冒號(hào):對應(yīng)一個(gè)參數(shù)。由于第21行age的set方法接收一個(gè)int類型的參數(shù),參數(shù)名為newAge,所以(int)newAge前面有一個(gè)冒號(hào):
5> 一定要記住:一個(gè)冒號(hào):對應(yīng)一個(gè)參數(shù),而且冒號(hào):也是方法名的一部分。因此第21行set方法的方法名是setAge:,而不是setAge
?
再加大一下難度,假如增加一個(gè)方法可以同時(shí)設(shè)置age和height,那么就應(yīng)該這樣寫:
1 - (void)setAge:(int)newAge andHeight:(float)newHeight;* 這個(gè)方法是動(dòng)態(tài)方法、沒有返回值,接收2個(gè)參數(shù),所以有2個(gè)冒號(hào):
* 這個(gè)方法的方法名是setAge:andHeight:
* 其實(shí)andHeight是可以省略的,它只是為了讓方法名念起來通順一點(diǎn),也讓(float)newHeight前面的冒號(hào):不那么孤單
?
2.在Student.m中實(shí)現(xiàn)方法
前面已經(jīng)在Student.h中聲明了3個(gè)方法,接下來一一實(shí)現(xiàn)它們
1 #import "Student.h" 2 3 @implementation Student 4 5 // age的get方法 6 - (int)age { 7 // 直接返回成員變量age 8 return age; 9 } 10 11 // age的set方法 12 - (void)setAge:(int)newAge { 13 // 將參數(shù)newAge賦值給成員變量age 14 age = newAge; 15 } 16 17 // 同時(shí)設(shè)置age和height 18 - (void)setAge:(int)newAge andHeight:(float)newHeight { 19 age = newAge; 20 height = newHeight; 21 } 22 @end第6行對age方法進(jìn)行了實(shí)現(xiàn),第12行對setAge:方法進(jìn)行了實(shí)現(xiàn),第18行對setAge:andHeight:方法進(jìn)行了實(shí)現(xiàn)
?
回到頂部六、跟Java的比較
如果是在Java中,一個(gè)Student.java文件就可以搞定成員變量和方法
1 public class Student { 2 protected int age; 3 protected float height; 4 5 public int no; 6 public int score; 7 8 private float weight; 9 10 /** 11 * age的get方法 12 */ 13 public int getAge() { 14 return age; 15 } 16 17 /** 18 * age的set方法 19 */ 20 public void setAge(int newAge) { 21 age = newAge; 22 } 23 24 /** 25 * 同時(shí)設(shè)置age和height 26 */ 27 public void setAgeAndHeight(int newAge, float newHeight) { 28 age = newAge; 29 height = newHeight; 30 } 31 }?
回到頂部七、創(chuàng)建對象
前面已經(jīng)定義了一個(gè)Student類,成員變量和方法都有了,接下來看一下怎么使用這個(gè)類創(chuàng)建對象。
由于OC程序的入口點(diǎn)是main函數(shù),所以在main.m文件中演示Student類的使用。
先上完整代碼
1 #import <Foundation/Foundation.h> 2 #import "Student.h" 3 4 int main(int argc, const char * argv[]) 5 { 6 @autoreleasepool { 7 Student *stu = [[Student alloc] init]; 8 9 [stu release]; 10 } 11 return 0; 12 }1.包含Student.h
因?yàn)橐玫絊tudent這個(gè)類,所以在第2行包含了它的頭文件
#import "Student.h"?
2.創(chuàng)建對象
1> 在Java中是使用關(guān)鍵字new來創(chuàng)建對象,比如new Student(),其實(shí)這句代碼做了2件事:
- 給對象分配存儲(chǔ)空間
- 調(diào)用Student的構(gòu)造方法進(jìn)行初始化
2> 在OC中創(chuàng)建對象也需要按順序做上面所述的2件事
1)調(diào)用Student類的靜態(tài)方法alloc分配存儲(chǔ)空間
Student *stu = [Student alloc];- OC是方法調(diào)用是用中括號(hào)[ ],方法調(diào)用者寫在括號(hào)左側(cè),方法名寫在括號(hào)右側(cè),中間留點(diǎn)空格。因此上面是調(diào)用了Student類的靜態(tài)方法alloc。
- 上面調(diào)用的alloc方法會(huì)返回分配好內(nèi)存的Student對象,在等號(hào)左邊用了一個(gè)指向Student類型的指針變量stu來接收這個(gè)對象,注意stu左邊的*號(hào)。所有OC對象都是用指針變量來接收的,如果你不了解指針,你記住下面這點(diǎn)就行了:利用類名定義一個(gè)變量時(shí),類名后面一定要帶個(gè)*號(hào)。
- alloc方法是這樣聲明的:
可以看到,它的返回值類型是id,這個(gè)id代表任何指針類型,你可以暫時(shí)理解為:id可以代表任何OC對象,類似于NSObject *。
?
2)調(diào)用Student對象的構(gòu)造方法init進(jìn)行初始化
前面調(diào)用alloc方法返回的Student對象stu是不能正常使用的,因?yàn)閮H僅是分配了內(nèi)存,并沒有進(jìn)行初始化,接下來調(diào)用對象的init方法進(jìn)行初始化
stu = [stu init];看清楚了,由于init是動(dòng)態(tài)方法,所以這里使用stu變量來調(diào)用,并不是使用類名來調(diào)用。init會(huì)返回已經(jīng)初始化完畢的對象,再次賦值給了stu變量。這時(shí)候的Student對象stu才能正常使用。
?
3)其實(shí),我們最常見的做法是將alloc和init連起來使用:
Student *stu = [[Student alloc] init];相信有面向?qū)ο箝_發(fā)經(jīng)驗(yàn)的你一眼就能看懂了,在main.m完整代碼的第7行。
?
3.銷毀對象
由于OC不支持垃圾回收,因此當(dāng)不再使用某個(gè)對象時(shí),需要調(diào)用對象的release方法釋放此對象。我們在第9行銷毀了stu對象。
[stu release];這個(gè)release方法在這里調(diào)用一次即可,不要覺得多調(diào)用多幾次,對象就會(huì)釋放地干凈一點(diǎn),這樣做會(huì)很危險(xiǎn),容易造成野指針錯(cuò)誤。
?
4.其他
1> 也可以調(diào)用靜態(tài)方法new快速創(chuàng)建一個(gè)對象
1 Student *stu = [Student new]; 2 3 [stu release];不過我們還是習(xí)慣使用alloc和init來創(chuàng)建對象
2>?前面我們調(diào)用了Student的alloc、init、new方法,但是你會(huì)發(fā)現(xiàn)Student.h中并沒有聲明這些方法,為什么能夠調(diào)用呢?原因很簡單,這些方法都是父類NSObject的,子類當(dāng)然可以調(diào)用父類的方法。
?
回到頂部八、訪問公共成員變量和方法
前面已經(jīng)成功創(chuàng)建了一個(gè)Student對象,接下來訪問一下它的公共變量和方法。
1 #import <Foundation/Foundation.h> 2 #import "Student.h" 3 4 int main(int argc, const char * argv[]) 5 { 6 @autoreleasepool { 7 Student *stu = [[Student alloc] init]; 8 9 // 訪問公共變量no 10 stu->no = 10; 11 12 // 調(diào)用setAge:方法設(shè)置變量age的值 13 [stu setAge:27]; 14 15 // 調(diào)用setAge:andHeight:方法同時(shí)設(shè)置變量age和height的值 16 [stu setAge:28 andHeight:1.88f]; 17 18 // 訪問公共變量no 19 int no = stu->no; 20 // 調(diào)用age方法獲取變量age的值 21 int age = [stu age]; 22 23 // 打印no和age的值 24 NSLog(@"no is %i and age is %i", no, age); 25 26 [stu release]; 27 } 28 return 0; 29 }1.第7行創(chuàng)建了Student對象,第26行銷毀了對象
2.第10行和第19行訪問了Student對象的公共成員變量no,如果不是公共變量,不能像這樣直接訪問。注意訪問方式:對象->成員變量
3.第13行調(diào)用了Student對象的setAge:方法,傳入?yún)?shù)27修改了成員變量age的值
4.第16行調(diào)用了Student對象的setAge:andHeight:方法,同時(shí)修改了成員變量age和height的值
5.第21行調(diào)用了Student對象的age方法獲取成員變量age的值
6.第24行輸出了age和no的值,輸出結(jié)果:
2013-04-06 21:54:56.221 第一個(gè)OC程序[1276:303] no is 10 and age is 28總結(jié)
- 上一篇: 别放任这些小毛病不管!它会扩大还会造成重
- 下一篇: 迪普科技以近50%份额全面中标国家电网2