Objective-C category 和 informal protocol

在查 NSURLConnection 的時候, 看到一堆重要的 method 被 deprecated 了, 感到相當困惑。讀了這篇說明才明白, 原來東西都在, 用法其實也沒什麼變, 只是宣告的方式變了。

首先要理解 Objective-C 的語法 Category:

@interface SomeClass (SomeCategory)
...
@end

在 ... 宣告的方法, 是對 SomeClass 的擴充, 這組擴充的名稱為 SomeCategory。

Category 可用在包含標準函式庫 (Foundation) 內的任何 class。這有什麼好處呢? 比方說你需要一個比較特別的 Set 操作, 像是 [mySet uniformRandomObject] 傳回 mySet 內隨機的一個物件。不論是用組合還是繼承的方式訂新的 class, 都不太方便。這時用 Category 就很方便了:

// NSSet+RandomOps.h
@interface NSSet (RandomOps)

-(id)uniformRandomObject;

@end

// NSSet+RandomOps.m
@implementation NSSet (RandomOps)

-(id)uniformRandomObject
{
   ...
}

@end

再來, Protocol 相當於 Java 的 interface, 也就是只有宣告但不帶實作的介面。另一方面, 只有宣告 Category 卻沒有提供實作的宣告, 就稱為 Informal Protocol。通常會宣告在 NSObject 上, 這樣任何客戶碼都可以實作需要的 method 而不用繼承其它 class。 NSURLConnection deprecated 的那些方法就是採用此方法。在 iOS 4.3 to iOS 5.0 API Differences 搜尋 "NSURLConnection.h" 可看到多數 callback 從 NSObject 裡移到新的 protocol NSURLConnectionDelegateNSURLConnectionDataDelegateNSURLConnectionDownloadDelegate 裡面。

Objective-C 2.0 以前 protocol 沒有 @optional 的語法。若希望 delegate 可以選擇性實作 callback methods, 只能使用 Informal Protocol。有了 @optional 語法後, 比較不需要用到 Informal Protocol。

Btw, Objective-C 同時有 static typing 和 dynamic typing 的效果, 還滿神奇的。不知當年訂這語言的人在想什麼, 雖然我喜歡使用 Python, 不過更偏好 static typing, 待用更多 Objective-C 後再來體會這種組合的優缺點。

留言

  1. 就我的理解 Objective-C runtime 基本上是 dynamic typing 的, static typing 僅存在 syntax checking 而已. 就連 method (objective-C似乎稱為selector)的 signature 也是不含型別的. 你可以用 id 這個型別來存取任何 objective-C object.

    回覆刪除
  2. 我的理解和你一樣, 差別在於我們用詞的定義可能不同。雖說用詞的定義比較次要, 保險起見查一下 wikipedia:
    http://en.wikipedia.org/wiki/Type_system#Type_checking
    A programming language is said to use static typing when type checking is performed during compile-time as opposed to run-time

    A programming language is said to be dynamically typed when the majority of its type checking is performed at run-time as opposed to at compile-time.

    結果 Objective-C 本身的介紹是寫: Typing discipline static, dynamic, weak
    http://en.wikipedia.org/wiki/Objective-C

    分不清那邊比較多, 就兩者都寫上去了 XD

    Btw, 寫 Python 的時候, 最大的不滿就是做些小修改也得跑一次程式才可確定沒有改爛, 有 compiler 幫忙抓出主要錯誤, 省事許多。

    Btw (2), 最近學 Objective-C 才明白為什麼 Objective-C++ 沒有抓出未實作 pure virtual method 的錯誤 (也可能是 compiler bug), 以前覺得這滿不合理的, 當時誤以為它如同 C/C++ 是「純種」 static typing, 現在就釋懷多了

    回覆刪除

張貼留言

這個網誌中的熱門文章

(C/C++ ) 如何在 Linux 上使用自行編譯的第三方函式庫

熟悉系統工具好處多多

virtualbox 使用 USB 裝置