Objective-C 編程全解-第04章 對象的類型和動態綁定

來源:互聯網
上載者:User

第04章 對象的類型和動態綁定

    Objective-C的一個重要特徵就是動態性,本章將對Objective-C的動態類型(dynamic typing)和動態綁定(dynamic binding)進行說明。


4.1 動態綁定

4.1.1 什麼是動態綁定

    Objective-C中的訊息是在運行時才去綁定的。運行時系統首先會確定接受者的類型(動態類型識別),然後根據訊息名在類的方法列表裡選擇相應的方法執行,如果沒有找到就到父類中去繼續尋找,假如一直找到NSObject也沒有找到就要調用的方法,就會報告不能識別訊息的錯誤。

    動態綁定(dynamic binding)指的就是在程式執行時才能確定對象的屬性和需要相應的訊息。


4.1.2 多態

    在物件導向的程式設計理論中,多態(polymorphism)是指,同一操作作用不不同的類的執行個體時,將產生不同的執行結果。即不同的類的對象收到相同的訊息時,也能得到不同的結果。

        polymorphic  [ˌpɒlɪ'mɔ:fɪk]  adj. 多形的,多態的,多形態的;  多晶形

        polymorphism  [ˌpɒlɪ'mɔ:fɪzəm]  n. 多型現象,多態性;  多機組合形式;  多型

        prism |ˈprɪzəm| noun 稜鏡

    多態是物件導向編程的一個重要特徵,大大增強了軟體的靈活性和擴充性。

    例如若使用面向過程的思想,則每增加一種處理就有可能需要增加一個分支,而且可能需要在所有相關的地方增加處理。但是使用多態,就可以大大減少類似情況,可能只需要增加一個類即可。


4.2 作為類型的類

4.2.1 把類作為一種類型

     我們可以把定義好的類 作為 對象的類型。如NSObject *object;


4.2.2 null 指標nil

    如果給nil變數發送訊息會怎麼樣呢。雖然這種寫法是完全有效,但是運行時不會有任何作用,訊息也不會被發送。

    如下例子:

        if((val = [list entryForKey:”NeXT]) != nil)

        {

            [val increment]; //increment |ˈɪŋkrəmənt| noun 增加、增值

        }

    給nil變數發送訊息,訊息也不會被發送,所以上面的程式就等價於下面的程式。

        val = [list entryForKey:”NeXT”];

        [val increment];


    第二種寫法雖然使程式變得更簡潔,但卻使程式變的更難理解。因為程式的本意是傳回值為nil時不做任何處理。另外,不注意的話這種寫法也會帶來各種各樣的錯誤,例如下面這段程式。

        if ((val = [list entryForKey:”NeXT”]) != nil)

        {

            [val setValue:n++];

        }

    雖然val是nil是訊息不會被發送,但是並不意味著[val setValue:n++]不會被執行。如果上面這段代碼中省略了val != nil的判斷,n++就仍然會被執行,這點同判斷語句中的“短路”有所不同。

    那麼,如果向nil發送訊息,那麼這個訊息的傳回值是什麼。一般來說,如果訊息對應的方法的傳回值是一個對象,那麼將返回nil;如果訊息對應的方法的傳回值是指標類型,將返回NULL;如果訊息對應方法的傳回值是整數類型,則將返回0。而如果傳回值的類型是以上這幾種類型以外的類型,例如結構體或者實數,那麼傳回值將是未定意的;

        typedef struct

        {

            int one;

            int two;

        } MyTestStruct;


        - (MyTestStruct)structTestFunc

        {

            MyTestStruct result = {1,2};

            return result;

        }


        test = nil;

        MyTestStruct myStruct = [test structTestFunc];

        NSLog(@"%d,%d,%lu",myStruct.one,myStruct.two,sizeof(myStruct));//0,0,8

        NSLog(@"%d,%d,%lu",[test structTestFunc].one,[test structTestFunc].two,sizeof([test structTestFunc]));//0,0,8



4.2.3 靜態類型檢查

    雖然在Objective-C中id資料類型可以用來儲存任何類型的對象,但絕大多數情況下我們還是將一個變數聲明為特定類的對象,這種情況稱為靜態類型。使用靜態類型時,編譯器在編譯時間可以進行類型檢查,如果類型不符合會提示警告。

    在Objective-C中,id類型是一種通用的資料類型,類似於C語言的(void*),可以用來儲存任何類的對象。在程式執行期間,這種資料類型真正的優勢就會體現出來,使用id類型結合多態,可以使程式具備更大的靈活性和延展性。但程式變靈活的同時,也需要付出代價,編譯器不會對id類型的變數進行檢查,這會導致程式更容易出錯。

    在一些複雜的程式中,使用強制類型轉換時,也一定要注意類型,否則就會引發執行階段錯誤。

    對於NSObject對象,即使進行強制類型轉換,實際執行時的方法也是有對象本應有的類型決定。


4.2.4 靜態類型檢查的總結

(6)若要判斷到底是哪個類的方法被執行了,不要看變數所聲明的類型,而要看實際執行時這個變數的類型。

(7)id類型並不是(NSObject*)類型,id類型和其他類之間沒有繼承關係。


    C++和Java的多態是基於類階層的,可以通過子類重寫父類中的方法來實現多態。這種類型的語言無法實現那種沒有繼承關係的多態,而OC中結合id類型可以做到這一點。


4.3 編程中的類型定義

4.3.1 簽名不一致時的情況

    訊息選取器(message selector)中並不包含參數和傳回值的類型的資訊,訊息選取器和這些類型資訊結合起來構成簽名(signature),簽名被用於在運行時標記一個方法。介面檔案中方法的定義也叫做簽名。

        NSArray * arry = @[@1,@2];

        [self signature:(NSString *)arry number:2];

        - (void)signature:(NSString*)str number:(NSInteger)num

        {

            NSLog(@"%@,%p,%u",str,str,num);

            /*

             2016-06-01 17:12:53.207 Test[1153:80130] (

             1,

             2

             ),0x7d276fa0,2

             */

        }

    Cocoa提供了類NSMethodSignature,以物件導向的方式來記錄方法的參數個數、參數類型和傳回值類型等資訊。這個類的執行個體也叫做方法簽名。

    重載(over loading)指的就是一個函數、運算子或方法定義有多種功能,並根據情況來選擇合適的功能。

    OC是動態語言,參數的類型是在運行時確定的,所以不支援這種根據參數類型的不同來調用不同函數的重載。OC可以通過動態綁定讓同一個訊息選取器執行不同的功能來實現重載。


4.3.2 類的前置聲明

    通過編譯指令@class告知編譯器某個符號是一個類名。這種寫法稱為類的前置聲明(forward declaration)

    class指令後面可以一次接很多個類,用“,”號分割,用“;”表示結束。前置聲明也可以聲明多次。如:

        @class NSString,NSArry,NSMutableArry;

        @class Volume;

    通過使用@class可以提升程式整體的編譯速度。但是要注意的是,如果新定義的類中要使用原有類的具體成員或方法,就一定要引入原有類的標頭檔。

    @class的另外一個好處是,當多個介面出現類的嵌套定義時,如果只是相互包含對方的標頭檔無法解決,則只能通過類的前置聲明來解決。


4.3.3 強制類型轉換的使用樣本

    雖然強制類型轉換的功能很強大,但會讓編譯器的類型檢查變得沒有意義,所以要盡量少用。不得不使用的情況下,要重新思考設計是否合理。


4.4 執行個體變數的資料封裝

4.4.1 執行個體變數的存取權限

ClassA.h

//

//  ClassA.h

//  Test

//

//  Created by ranzhou on 16/6/1.

//  Copyright © 2016年 ranzhouee. All rights reserved.

//


#import <Foundation/Foundation.h>


@interface ClassA : NSObject

{

    NSString *A_default;    //預設為protected

    

@public

    NSString *A_public;

    

@protected

    NSString *A_protected;

    

@private

    NSString *A_private;

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.