id 和 NSObject區別
- 1.NSObject包含了一些其他的方法,需要實現NSObject協議,可以用NSObject來表示id,但是不能用id來表示NSObject。
- 2.id型別是執行時的動態型別,編譯器無法知道它的真實型別,在編譯的時候不會被檢查,即使你傳送一個id型別沒有的方法,也不會產生編譯警告。而NSObject在編譯的時候被被檢查是否含有一些錯誤的方法。
- 3.id型別是一個Objective-C物件,但並不是都指向繼承自NSOjbect的物件,比如NSProxy就不從NSObject繼承。
- 4.定義id的時候不需要*,而定義NSOject的時候需要。
下面三種的區別:
- id foo1;
- NSObject *foo2;
- id foo3;
第一種是最常用,它簡單地申明瞭指向物件的指標,沒有給編譯器任何型別資訊,因此,編譯器不會做型別檢查。但也因為是這樣,你可以傳送任何資訊給id型別的物件。這就是為什麼+alloc返回id型別,但呼叫[[Foo alloc] init]不會產生編譯錯誤。
因此,id型別是執行時的動態型別,編譯器無法知道它的真實型別,即使你傳送一個id型別沒有的方法,也不會產生編譯警告。
我們知道,id型別是一個Objective-C物件,但並不是都指向繼承自NSOjbect的物件,即使這個型別和NSObject物件有很多共同的方法,像retain和release。要讓編譯器知道這個類繼承自NSObject,一種解決辦法就是像第2種那樣,使用NSObject靜態型別,當你傳送NSObject沒有的方法,像length或者count時,編譯器就會給出警告。這也意味著,你可以安全地使用像retain,release,description這些方法。
因此,申明一個通用的NSObject物件指標和你在其它語言裡做的類似,像Java,但其它語言有一定的限制,沒有像Objective-C這樣靈活。並不是所有的Foundation/Cocoa物件都繼承息NSObject,比如NSProxy就不從NSObject繼承,所以你無法使用NSObject*指向這個物件,即使NSProxy物件有release和retain這樣的通用方法。為了解決這個問題,這時候,你就需要一個指向擁有NSObject方法物件的指標,這就是第3種申明的使用情景。
id告訴編譯器,你不關心物件是什麼型別,但它必須遵守NSObject協議(protocol),編譯器就能保證所有賦值給id型別的物件都遵守NSObject協議(protocol)。這樣的指標可以指向任何NSObject物件,因為NSObject物件遵守NSObject協議(protocol),而且,它也可以用來儲存NSProxy物件,因為它也遵守NSObject協議(protocol)。這是非常強大,方便且靈活,你不用關心物件是什麼型別,而只關心它實現了哪些方法。
如果你不需要任何的型別檢查,使用id,它經常作為返回型別,也經常用於申明代理(delegate)型別。因為代理型別通常在執行時,才會檢查是否實現了那些方法。
如果真的需要編譯器檢查,那你就考慮使用第2種或者第3種。很少看到NSObject*能正常執行,但id無法正常執行的。使用協議(protocol)的優點是,它能指向NSProxy物件,而更常用的情況是,你只想知道某個物件遵守了哪個協議,而不用關心它是什麼型別。
相關文章
- 知識點:id 和NSObject *對比,以及id <NSObject>介紹Object
- NSObject +(void)load 和+(void)initialize 方法的理解Object
- UUID和GUID的區別GUI
- clientWidth和offsetWidth的區別client
- UDID和UUID的區別UI
- UUID 和 GUID 的區別GUI
- MID和UMPC的區別
- rowid和rownum的區別
- SEAndroid和普通android的區別Android
- Overload 和 和 Override 的區別IDE
- android中Invalidate和postInvalidate的區別Android
- Scrapy框架-Spider和CrawlSpider的區別框架IDE
- max-width和width的區別
- width:auto和width:100%區別
- ios instancetype和id的區別iOS
- JS中class和id的區別JS
- 轉:IDOCBAPIRFC區別和聯絡API
- Android中 @和?區別以及?attr/**與@style/**等的區別Android
- NSObject class和NSObject protocol的關係(抽象基類與協議)ObjectProtocol抽象協議
- docment.getelementbyid 和jquery裡的$(#'id')區別jQuery
- 你知道void和Void的區別嗎
- 元素的尺寸 offsetWidth和clientWidth的區別client
- android:gravity和android:layout_gravity區別Android
- View.findViewById()和Activity.findViewById()區別View
- oracle中rownum和rowid的區別Oracle
- 請教strategy 和 bridge的區別
- NSObject 的 initialize 和 load 方法Object
- NSObject的load和initialize方法Object
- NSObject 的 load 和 initialize 方法Object
- android-invalidate和postInvalidate 的區別及使用Android
- 自增長列和序列的區別(identity與sequence的區別)IDE
- Client Side Cache 和 Server Side Cache 的區別clientIDEServer
- android:layout_gravity 和 android:gravity 的區別Android
- IDENT_CURRENT、@@IDENTITY 和 SCOPE_IDENTITY 的區別IDE
- 和區別
- querySelector和getElementById之間的區別
- Android之drawable和mipmap目錄區別Android
- Android核心和Linux核心的區別AndroidLinux