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

4.2 類與對象

現在,我就要創建真正的機器人類型了。

與大多面向對象編程語言的區別在于,在Objective-C中并不使用class關鍵字來定義類,而是使用兩個部分來定義類,包括接口(interface)部分和實現(implementation)部分。

理論上講,我們可以將類的接口部分和實現部分都放在一個文件中,但我們一般會將接口部分定義在頭文件(.h)中,而將實現部分定義在相應的模塊文件(.m)中。

■4.2.1 接口部分

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

圖4-1 創建類

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

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

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

在CRobot類中,我們聲明了一個名為move的實例方法,它沒有返回值(使用void關鍵字聲明),稍后,會看到更多關于方法的內容。接下來,我們先來看一看如何在實現部分定義這個方法。

■4.2.2 實現部分

下面的代碼,我們將在CRobot.m文件中看到CRobot類成員的具體實現。

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

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

在這里,可以看到move方法的實現代碼,它的功能很簡單,只是顯示一條信息。

請注意,在類中的方法并沒有使用小括號()來包含參數。實際上,其參數的定義方式與函數有所不同,稍后,我們會看到相關內容。

■4.2.3 創建對象(實例化)

下面的代碼,我們演示了如何在main()函數中使用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()函數中,我們使用如下代碼聲明了一個CRobot類的實例,即robot5對象。

    CRobot *robot5

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

接下來,我們注意給robot5對象賦值的代碼,它實際上完成了對象的實例化過程,這個過程共調用了兩個方法,即alloc方法和init方法,也許大家會問,我們并沒有定義這兩個方法,它們是從哪里來的呢?答案就是,它們是從繼承NSObject類而來的,也就是說,這兩個方法是定義在NSObject類中的,由于CRobot是NSObject類的子類,所以,我們可以在CRobot類中使用這兩個方法。

請注意,并不是基類中所有成員都能被子類訪問的,這與類成員的訪問級別有關,稍后我會討論相關主題。

最后,我們調用了robot5對象的move方法,在Objective-C中,類或對象的方法調用,其基本格式如下。

    [<類或對象> <方法名和參數>];

調用類或對象中的方法時,需要使用一對方括號[]包含起來,如果你學習過C#或Java等編程語言,可能對這種方法的調用格式有些不適應,不過,用著用著也就習慣了。

■4.2.4 類的成員

前面的示例已經介紹了如何定義一個簡單的類和方法,以及如何使用對象及其成員。實際開發中,類成員的定義會比前面的示例復雜得多,我們先來了解一些關于類成員定義和應用的基礎知識。

1.屬性和方法

定義一個類時,接口中定義的成員也就是類型對外公開的成員,主要包括屬性和方法,屬性用于定義對象的特性,而方法(任務)則用于定義對象可執行的動作。稍后,我們會詳細討論屬性和方法的創建與使用。

2.實例方法和類方法

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

    -(void) move;

實例方法的特點是,它必須由對象,即類的實例來調用。

另一種方法是類方法,它由類來調用,類方法使用加號(+)定義。

    +(void) methodName;

調用類方法時,直接使用類的名稱。

    [CRobot methodName];

更多關于方法定義的內容稍后討論。

3.實例變量

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

我們可以在類的接口部分或實現部分定義實例變量,此時,應在緊跟接口或實現指令后的一對花括號{}之間,如下面的代碼,我們在CRobot類的接口部分定義了counter實例變量。

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

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

實現部分定義的實例變量,只能用于當前類中的實例方法,相當于@private(私有的)訪問級別。如下面的代碼。

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

如果想簡單點,還可以直接在接口部分定義全部的實例變量,并指定其訪問級別,如下面的代碼。

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

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

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

不過,在類中使用公共的實例變量并不是好的應用方式,如果我們需要使用對象的數據,可以將這個數據定義為屬性。

4.訪問級別

定義一個類時,有些成員是需要提供給外部代碼調用的,而有些成員則只能在類的內部使用,此時,我們就應該考慮成員的訪問級別問題。

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

主站蜘蛛池模板: 邯郸市| 介休市| 鹤岗市| 云林县| 呼伦贝尔市| 隆安县| 来宾市| 屏东市| 玉树县| 密云县| 天镇县| 五寨县| 樟树市| 乳源| 龙南县| 富民县| 宜良县| 玛多县| 永德县| 宁波市| 四会市| 寻乌县| 上思县| 电白县| 綦江县| 新巴尔虎右旗| 德庆县| 鹰潭市| 内江市| 汝阳县| 和林格尔县| 志丹县| 浦县| 周口市| 高唐县| 维西| 凤山市| 天柱县| 城口县| 唐海县| 阳山县|