OC學習篇之---類的定義,oc---定義
之前已經介紹了OC中的一個程式HelloWorld:http://blog.csdn.net/jiangwei0910410003/article/details/41578003,今天我們繼續學習OC中類的相關知識。
OC和C的最大區別就是具有了物件導向的功能,那麼說到物件導向,就不得不說類這個概念了,如果學過Java的話,那麼對類和對象的概念就不陌生了,因為Java是非常純正的物件導向設計語言。關於類和對象的概念,這裡就不仔細介紹了,網上有各種解釋。我們之間來開一下OC中如何定義一個類,如何執行個體化出一個對象等。
首先我們建立一個工程,系統會自動建立main.m檔案的,這時候,我們右鍵項目,選擇New File..
然後選擇OS X中的Source,在選擇Cocoa Class,點擊下一步
點擊下一步
這裡填寫以下類的名稱,這個和Java中是類似的了,點擊下一步:
我們可以看到,建立了一個Person類,但是這個和Java就有點區別了,一個類是有兩部分構成的,一個是類的標頭檔Person.h(一般是在該檔案中做定義工作的),還有一個是Person.m檔案,這個一般是實現標頭檔中定義的內容。這個也是延續了C語言中的項目結構吧。一般標頭檔只負責定義功能,.c檔案負責實現具體功能的。這裡也是類似吧。
下面來看一下Person.h標頭檔中類的定義格式:
// Person.h// 02_ClassDemo//// Created by jiangwei on 14-10-10.// Copyright (c) 2014年 jiangwei. All rights reserved.//#import <Foundation/Foundation.h>@interface Person : NSObject{ //在{}中定義屬性(全域變數/執行個體變數) //注意:只能定義不能賦值,因為這裡只是在做聲明操作,不能賦值的 //加上底線,為了區分局部變數 NSString *_name;//姓名,預設值是nil:null 指標,可以查看定義:#define nil NULL NSInteger _age;//年齡,預設值是0}//定義方法//-:執行個體方法,+:類方法//格式:方法說明 (傳回型別) 方法名 : (參數類型)參數名稱//注意方法名是shopping:,不是shopping,這個要注意- (void)shopping:(float)price;//定義方法設定屬性值(注意setXXX)- (void)setName:(NSString *)name;- (void)setAge:(NSInteger)age;//定義方法的擷取屬性值(注意不是getXXX,而是直接的屬性名稱,因為getXXX在OC中還有其他用途)- (NSString *)name;- (NSInteger)age;//多個參數的方法定義//方法名兩部分組成的:setName: setAge:- (void)setName:(NSString *)name setAge:(NSInteger)age;//或者方法名:setName: :,後面的可以省略,但是這種方式不建議使用//- (void)setName:(NSString *)name :(NSInteger)age;//類方法//在這個方法中是無法訪問屬性的,因為屬性是屬於對象的,不是類的+ (Person *)newPerson;@end首先看到類的定義的關鍵字是:
@interface
一般類的定義格式為:
@interface 類名:NSObject{
定義屬性
}
定義方法
這裡有幾點需要說明:
1、OC中任何一個類都是繼承NSObject,這個和Java中的Object是一個概念的,所以這裡需要匯入
#import <Foundation/Foundation.h>
其實Java中的Object對象是在java.lang.*包中的,不過Java並不會匯入這個包,因為Object類的類載入器決定的,不需要匯入的.
2、這裡的繼承符號和C++中是一樣的,使用冒號:
3、在{}類定義類的屬性,關於這裡所說的屬性和Java中的屬性不是一個概念了,OC中只要定義在{}中的欄位就是類的屬性,而Java中是有getXXX/setXXX的方法,才叫屬性。同時也得注意,OC中類中定義的屬性名稱是以底線:"_"開頭,為什麼要這樣做,就是為了區分後面的局部變數與其重名了,當然我們在Java中一般是以m開頭,或者其他方式,Java中沒有那麼強的規範,但是OC中還是強烈建議用這種方式的,還有一點要注意,在定義設定方法的時候,一般樣式是setXXX,但是在定義取值的方法的時候直接是XXX,而不是getXXX了,這個也是和Java有區別的,至於為什麼這麼做,因為get開頭的方法已經有其他用處了,後面會說到。這裡就注意一下就可以了。
4、在屬性定義的後面就是簡單的定義方法了
下面在來看一下如何定義方法:
OC中定義方法和Java語言有很大的不同,所以這裡很難記住,如果不常用的話,看一下方法的定義格式:
方法說明 (傳回型別) 方法名 : (參數類型)參數名稱
1、方法說明有兩種:
一種是減號:"-",表示該方法是對象方法,就是必須用對象執行個體才能調用的
一種是加號:"+",表示該方法是類方法,就是可以用類直接調用的,不需要執行個體化對象的,類似於Java中的static方法
2、傳回型別:這個就簡單了,和Java語言很類似了
3、方法名:方法名和Java中就不太一樣了,看個例子:
//注意方法名是shopping:,不是shopping,這個要注意- (void)shopping:(float)price;
這個方法的方法名是
shopping: 是包含冒號的,再看個例子:
//多個參數的方法定義//方法名兩部分組成的:setName: setAge:- (void)setName:(NSString *)name setAge:(NSInteger)age;
多參數的方法定義,那麼這個方法的方法名就是setName:setAge:
4、(參數類型)參數名稱:這個和Java也是有很大的區別的,感覺像是和Java中定義的相反了,他用括弧把類型括起來了。OC中的物件類型和Java中的使用不一樣,OC中的物件類型相當於C中指標定義樣式(類名 *),這點需要注意。
當然在類定義的結束地方使用@end關鍵字的
看完了類的定義,下面在來看一下類的具體實現了:
Person.m
//// Person.m// 02_ClassDemo//// Created by jiangwei on 14-10-10.// Copyright (c) 2014年 jiangwei. All rights reserved.//#import "Person.h"@implementation Person//實現方法- (void) shopping : (float)price{ NSLog(@"%@ shopping %f",_name,price);}- (void)setName:(NSString *)name{ _name = name;}- (void)setAge:(NSInteger)age{ _age = age;}- (NSString *)name{ return _name;}- (NSInteger)age{ return _age;}- (void)setName:(NSString *)name setAge:(NSInteger)age{ _name = name; _age = age;}+ (Person *)newPerson{ return [[Person alloc] init];}@end看到類的實現使用的是@implementation 關鍵字
在實現的源檔案中,必須匯入類的定義的標頭檔
#import "Person.h"
這樣的一種形式,和C語言中的工程結構非常相似。
然後就是對標頭檔中定義的一些方法的具體實現了,而且在實現檔案中,我們可以訪問類中定義的屬性。其他的就沒有什麼難度了,就不在細說了,同樣的類的結束標誌:@end
類定義和實現都介紹完了,下面來看一下如何使用吧:
main.m
//// main.m// 02_ClassDemo//// Created by jiangwei on 14-10-10.// Copyright (c) 2014年 jiangwei. All rights reserved.////類的定義放在.h檔案中//類的實現放在.m檔案中//定義一個類的步驟//定義類名、編寫類的屬性、編寫類的行為#import <Foundation/Foundation.h>#import "Person.h"int main(int argc, const char * argv[]) { @autoreleasepool { //建立對象 //在記憶體中申請一塊記憶體地區 //Person *person = [Person alloc]; //調用初始化方法,初始化一些預設資料 //可能上面申請的記憶體之前有被使用過,還會有以前的資料。所以我們需要將其資料清空,這時候就會將預設值進行賦值(相當於清空操作) //person = [person init]; //合并 //這裡申請了兩塊記憶體:一個是對象指標變數,一個是alloc申請的 //可以看出alloc/init方法是類方法、可以查看NSObject對象的定義 Person *person = [[Person alloc] init]; //還有另外的一種方式建立一個對象,但是這種方式不建議使用,因為這種方式相當於把上面的兩個合并 //有時候我們需要將上面的兩個步驟進行分開操作的 //Person *person1 = [Person new]; //設定名字 [person setName:@"jaingwei"]; //調用執行個體方法shopping [person shopping:200]; Person *person1 = [[Person alloc] init]; [person1 setName:@"huangdaoyang"]; [person1 shopping:300]; //同時設定兩個屬性的值,但是這種方式不建議使用,建議使用set方法 [person1 setName:@"huangdaoyang" setAge:22]; //get方法調用 NSString *person_name = [person name]; NSLog(@"name is %@",person_name); NSString *person1_name = [person1 name]; NSLog(@"name is %@",person1_name); //類方法調用 Person *person2 = [Person newPerson]; [person2 setName:@"shixin" setAge:22]; [person2 shopping:400]; //null 指標 Person *person3 = nil; //不執行任何操作,但是也不會報錯null 指標異常 [person3 setName:@"Null 物件" setAge:22]; } return 0;}OC中執行個體化一個對象的方式是:
Person *person = [[Person alloc] init];
首先是指標類型的樣式定義一個變數,然後是調用類的alloc方法,接著調用init方法,這裡有點比較奇怪,我們在定義Person類的時候,沒有定義alloc和init方法,這裡為什麼不報錯呢?這個就和Java很相似了,因為OC中任何類都是整合NSObject類的,那麼自然想到了這兩個方法是NSObject定義的。而且我們可以看到alloc方法是類方法,init是對象方法
同時,OC中的方法調用方式:
對象方法:[物件變數 方法名 參數]
類方法:[類名 方法名 參數]
這裡執行個體化一個對象和Java中有很大的區別的,Java中直接new一個就可以了。這裡需要調用兩個方法alloc和init
可以這麼理解吧:alloc相當於給這個對象分配記憶體空間,init是調用這個類的構造方法,對屬性和欄位進行初始化操作
當然上面的執行個體化操作也可以變成兩步:
Person *person = [Person alloc];//調用初始化方法,初始化一些預設資料//可能上面申請的記憶體之前有被使用過,還會有以前的資料。所以我們需要將其資料清空,這時候就會將預設值進行賦值(相當於清空操作)person = [person init];
但是OC中建議的方式還是上面那種。
對象方法的調用,設定名字:
//設定名字[person setName:@"jaingwei"];
多個參數的對象方法調用,同時設定名字和年齡
//同時設定兩個屬性的值,但是這種方式不建議使用,建議使用set方法[person1 setName:@"huangdaoyang" setAge:22];
類方法的調用:
//類方法調用Person *person2 = [Person newPerson];
總結
好了,關於OC中類的定義以及實現,如何使用就介紹到這裡了,我們在學習的過程中可以和一門物件導向語言相比較學習,這樣可能會學習的快點。