官术网_书友最值得收藏!

4.2 類與對(duì)象

現(xiàn)在,我就要?jiǎng)?chuàng)建真正的機(jī)器人類型了。

與大多面向?qū)ο缶幊陶Z(yǔ)言的區(qū)別在于,在Objective-C中并不使用class關(guān)鍵字來(lái)定義類,而是使用兩個(gè)部分來(lái)定義類,包括接口(interface)部分和實(shí)現(xiàn)(implementation)部分。

理論上講,我們可以將類的接口部分和實(shí)現(xiàn)部分都放在一個(gè)文件中,但我們一般會(huì)將接口部分定義在頭文件(.h)中,而將實(shí)現(xiàn)部分定義在相應(yīng)的模塊文件(.m)中。

■4.2.1 接口部分

接下來(lái)的測(cè)試工作,我們將繼續(xù)使用SimpleOC項(xiàng)目;在Xcode中,通過(guò)菜單“File”→“New”→“File”,選擇OS X下的Source,然后選擇Cocoa Class,接下來(lái),需要我們指定類的名稱(Class)及其基類(Subclass of),如圖4-1所示。

圖4-1 創(chuàng)建類

單擊“Next”按鈕,我們還需要指定代碼保存的路徑,然后,Xcode會(huì)自動(dòng)為創(chuàng)建以類的名稱命名的頭文件和代碼文件。首先,我們看一看頭文件中的接口部分,如下面的代碼(CRobot.h文件)。

    #ifndef __CRobot_h__
    #define __CRobot_h__
    #import <Foundation/Foundation.h>
    @interface CRobot : NSObject
    -(void) move;
    @end
    #endif

我們可以看到,類的接口部分定義在@interface和@end指令之間,而類的名稱定義在@interface指令后面,緊跟其后的冒號(hào)(:)含義為繼承,本例中,我們定義的CRobot類繼承自NSObject類。

在CRobot類中,我們聲明了一個(gè)名為move的實(shí)例方法,它沒(méi)有返回值(使用void關(guān)鍵字聲明),稍后,會(huì)看到更多關(guān)于方法的內(nèi)容。接下來(lái),我們先來(lái)看一看如何在實(shí)現(xiàn)部分定義這個(gè)方法。

■4.2.2 實(shí)現(xiàn)部分

下面的代碼,我們將在CRobot.m文件中看到CRobot類成員的具體實(shí)現(xiàn)。

    #import "CRobot.h"
    @implementation CRobot
    -(void) move
    {
        NSLog(@"機(jī)器人移動(dòng)");
    }
    @end

在這里,我們可以看到,類的實(shí)現(xiàn)部分定義在@implementation和@end指令之間。在@implementation指令后需要類的名稱,但不需要再次指定繼承哪個(gè)類。

在這里,可以看到move方法的實(shí)現(xiàn)代碼,它的功能很簡(jiǎn)單,只是顯示一條信息。

請(qǐng)注意,在類中的方法并沒(méi)有使用小括號(hào)()來(lái)包含參數(shù)。實(shí)際上,其參數(shù)的定義方式與函數(shù)有所不同,稍后,我們會(huì)看到相關(guān)內(nèi)容。

■4.2.3 創(chuàng)建對(duì)象(實(shí)例化)

下面的代碼,我們演示了如何在main()函數(shù)中使用CRobot類。

    #import <Foundation/Foundation.h>
    #import "CRobot.h"
    int main(int argc, const char *argv[])
    {
        @autoreleasepool {
            CRobot *robot5 = [[CRobot alloc] init];
            [robot5 move];
    }
    return 0;
    }

代碼中,我們需要使用#import指令引用CRobot.h文件。然后,在main()函數(shù)中,我們使用如下代碼聲明了一個(gè)CRobot類的實(shí)例,即robot5對(duì)象。

    CRobot *robot5

大家可以看到,對(duì)象是被定義為指針類型的,這就是加*的意義。

接下來(lái),我們注意給robot5對(duì)象賦值的代碼,它實(shí)際上完成了對(duì)象的實(shí)例化過(guò)程,這個(gè)過(guò)程共調(diào)用了兩個(gè)方法,即alloc方法和init方法,也許大家會(huì)問(wèn),我們并沒(méi)有定義這兩個(gè)方法,它們是從哪里來(lái)的呢?答案就是,它們是從繼承NSObject類而來(lái)的,也就是說(shuō),這兩個(gè)方法是定義在NSObject類中的,由于CRobot是NSObject類的子類,所以,我們可以在CRobot類中使用這兩個(gè)方法。

請(qǐng)注意,并不是基類中所有成員都能被子類訪問(wèn)的,這與類成員的訪問(wèn)級(jí)別有關(guān),稍后我會(huì)討論相關(guān)主題。

最后,我們調(diào)用了robot5對(duì)象的move方法,在Objective-C中,類或?qū)ο蟮姆椒ㄕ{(diào)用,其基本格式如下。

    [<類或?qū)ο?gt; <方法名和參數(shù)>];

調(diào)用類或?qū)ο笾械姆椒〞r(shí),需要使用一對(duì)方括號(hào)[]包含起來(lái),如果你學(xué)習(xí)過(guò)C#或Java等編程語(yǔ)言,可能對(duì)這種方法的調(diào)用格式有些不適應(yīng),不過(guò),用著用著也就習(xí)慣了。

■4.2.4 類的成員

前面的示例已經(jīng)介紹了如何定義一個(gè)簡(jiǎn)單的類和方法,以及如何使用對(duì)象及其成員。實(shí)際開(kāi)發(fā)中,類成員的定義會(huì)比前面的示例復(fù)雜得多,我們先來(lái)了解一些關(guān)于類成員定義和應(yīng)用的基礎(chǔ)知識(shí)。

1.屬性和方法

定義一個(gè)類時(shí),接口中定義的成員也就是類型對(duì)外公開(kāi)的成員,主要包括屬性和方法,屬性用于定義對(duì)象的特性,而方法(任務(wù))則用于定義對(duì)象可執(zhí)行的動(dòng)作。稍后,我們會(huì)詳細(xì)討論屬性和方法的創(chuàng)建與使用。

2.實(shí)例方法和類方法

在前面定義的CRobot類中,我們定義的move屬于實(shí)例方法,使用減號(hào)(-)定義。

    -(void) move;

實(shí)例方法的特點(diǎn)是,它必須由對(duì)象,即類的實(shí)例來(lái)調(diào)用。

另一種方法是類方法,它由類來(lái)調(diào)用,類方法使用加號(hào)(+)定義。

    +(void) methodName;

調(diào)用類方法時(shí),直接使用類的名稱。

    [CRobot methodName];

更多關(guān)于方法定義的內(nèi)容稍后討論。

3.實(shí)例變量

在類中,可以定義一些實(shí)例變量,這些變量可以在實(shí)例方法中調(diào)用,我們還可以通過(guò)@public、@private、@protected指令指定實(shí)例變量的適用范圍(稱為作用域或訪問(wèn)級(jí)別)。

我們可以在類的接口部分或?qū)崿F(xiàn)部分定義實(shí)例變量,此時(shí),應(yīng)在緊跟接口或?qū)崿F(xiàn)指令后的一對(duì)花括號(hào){}之間,如下面的代碼,我們?cè)贑Robot類的接口部分定義了counter實(shí)例變量。

    @interface CRobot : NSObject
    {
        int counter;
    }
    -(void) move;
    @end

在接口部分定義的實(shí)例變量,其默認(rèn)使用范圍是@protected(受保護(hù)的),這些實(shí)例變量可以在當(dāng)前類或其子類的實(shí)例方法中使用。

實(shí)現(xiàn)部分定義的實(shí)例變量,只能用于當(dāng)前類中的實(shí)例方法,相當(dāng)于@private(私有的)訪問(wèn)級(jí)別。如下面的代碼。

    @implementation CRobot
    {
        int counter;
    }
    // 其他代碼
    @end

如果想簡(jiǎn)單點(diǎn),還可以直接在接口部分定義全部的實(shí)例變量,并指定其訪問(wèn)級(jí)別,如下面的代碼。

    @interface CRobot : NSObject
    {
    @private
        int counter = 0;
    @protected
        int x;
        int y;
    @public
        int identity;
    }
    -(void)move;
    @end

其中,counter變量為私有的實(shí)例變量,只能在本類中的實(shí)例方法中使用。x和y變量定義為受保護(hù)的實(shí)例變量,可以在本類或其子類的實(shí)例方法中使用,而identity變量則定義為公共的,可以由CRobot類型的對(duì)象使用→運(yùn)算符調(diào)用,如下面的代碼。

    CRobot *robot5 = [[CRobot alloc] init];
    robot5→identity = 5;
    NSLog(@"當(dāng)前ID : %i", robot5→identity);

不過(guò),在類中使用公共的實(shí)例變量并不是好的應(yīng)用方式,如果我們需要使用對(duì)象的數(shù)據(jù),可以將這個(gè)數(shù)據(jù)定義為屬性。

4.訪問(wèn)級(jí)別

定義一個(gè)類時(shí),有些成員是需要提供給外部代碼調(diào)用的,而有些成員則只能在類的內(nèi)部使用,此時(shí),我們就應(yīng)該考慮成員的訪問(wèn)級(jí)別問(wèn)題。

一般來(lái)講,我們將公共成員(屬性和方法)聲明在接口部分,然后在實(shí)現(xiàn)部分實(shí)現(xiàn)它們;而只限于本類或其子類使用的成員則應(yīng)該定義在類的實(shí)現(xiàn)部分。

主站蜘蛛池模板: 齐河县| 永靖县| 临桂县| 沾化县| 高密市| 边坝县| 建水县| 米脂县| 什邡市| 济阳县| 吉木乃县| 古浪县| 新田县| 乌恰县| 蓬安县| 巴里| 桦南县| 宾阳县| 宝应县| 丽江市| 娄烦县| 绥宁县| 吉林市| 山东省| 龙山县| 泸水县| 淮安市| 无棣县| 高安市| 南丹县| 佛坪县| 营山县| 社会| 黑山县| 通州区| 静乐县| 玉环县| 崇仁县| 行唐县| 黔江区| 当阳市|