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:空指針,可以查看定義:#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 charchar * 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];
- //空指針
- Person *person3 = nil;
- //不執行任何操作,但是也不會報錯空指針異常
- [person3 setName:@"空對象" 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中類的定義以及實現,如何使用就介紹到這里了,我們在學習的過程中可以和一門面向對象語言相比較學習,這樣可能會學習的快點。