[譯]2013-10-25 NSObject: the Class and the Protocol

原文連接: https://mikeash.com/pyblog/friday-qa-2013-10-25-nsobject-the-class-and-the-protocol.html



Reader Tomas Bouda asks: what's the deal with the NSObject protocol? There are two NSObjects in Cocoa, a class and a protocol. Why both? What purpose do they serve? In today's article, I'll explore the answer to this question.
讀者Tomas Bouda問我:「NSObject協議應該怎麼理解呢?在Cocoa中有兩處NSObject,一處是NSObject類,另外一處是NSObject協議。爲啥會有兩個呢?他們到底有什麼做用?」。在今天的文章裏,我將會探討這個問題。

Namespaces
命名空間

First, let's look at  how these two entities with the same name can coexist. Classes and protocols in Objective-C inhabit entirely separate namespaces. You can have a class and a protocol, which are unrelated at the language level, with the same name. That's the case with NSObject.
首先,讓咱們看看怎麼會有兩個名字相同的實體同時存在呢。在Objectice-C中,類和協議處於徹底不一樣的命名空間。你徹底能夠擁有名字相同的類和協議,可是要知道,它們在語言層面是沒有半毛錢關係的。那兩個NSObject的問題就明瞭了。

If you look at the language, there are no places where you can use either a class name or a protocol name. Class names can be used as the target of message sends, in @interface declarations, and as type names. Protocols can be used in some of the same places, but always in a different way. There's no ambiguity in having one of each with the same name.
縱觀Objective-C這個語言,用的不是類名,就是協議名。類名(Class names)能夠用做消息發送的目標對象,用在@interface聲明的時候,用做類型名稱。協議(Protocols)也能夠用在跟類名相同的地方,可是使用的方式跟類不同。在語言層面,相同名字的類和協議不會形成任何歧義。

Root Classes
根類

NSObject the class is a root class. A root class is a class at the very top of the hierarchy, meaning that it has no superclass. In Objective-C, unlike some languages like Java, there can be more than one root class.
NSObject是一個根類。根類是在繼承關係中很是高層次的類,就是它沒有父類。Objectice-C跟Java不同,Objectice-C能夠有多個根類。

Java has a single root class, java.lang.Object, which every other class directly or indirectly inherits from. Because of this, Java code can count on any object it encounters implementing the basic methods in java.lang.Object.
Java只有一個根類,java.lang.Object,每個其餘的類都直接或間接的繼承自它。所以,在Java代碼中,你能夠信賴任何實現了java.lang.Object中基本方法的對象。

Cocoa has multiple root classes. In addition to NSObject there's also NSProxy and some other assorted root classes. This is part of the reason for the NSObject protocol. The NSObject protocol defines a set of basic methods that all root classes are expected to implement. This way, code can count on those methods being there.
Cocoa有多個根類。除了NSObject類,還有NSProxy和其餘的一些根類。這也許是爲何會有NSObject協議。NSObject協議定義了一系列的基本方法,全部根類都被要求實現這些基本方法。經過這種方式,代碼就能夠信任來自協議中的那些方法。

The NSObject class conforms to the NSObject protocol, which means that the NSObject class implements these basic methods:
NSObject類遵循NSObject協議,所以NSObject類的實例會實現NSObject協議中定義的那些基本方法:

@interface NSObject <NSObject>

NSProxy also conforms to the NSObject protocol:
NSProxy類也遵循NSObject協議:

@interface NSProxy <NSObject>

The NSObject protocol contains methods like hash, isEqual:, description, etc. The fact that NSProxy conforms to NSObject means that you can still count on instances of NSProxy implementing these basic NSObject methods.
NSObject協議包括hash,isEqual:,description方法等。由於NSProxy也遵循NSObject協議,所以你也能夠信任實現了NSObject協議的NSProxy實例。

An Aside About Proxies
順便說說Proxies

While we're at it, just why is there an NSProxy root class?
儘管咱們知道了有NSProxy這個類,可是爲何要有這個根類呢?

There are some cases where it's useful to have a class that doesn't implement very many methods. As the name suggests, proxy objects are a common case where this is useful. The NSObject class implements a lot of stuff beyond the NSObject protocol, such as key-value coding, that you don't necessarily want.
有些狀況下,一個沒有實現太多方法的類是頗有用的。就像NSProxy這個名字同樣,代理對象一般是頗有用處的。NSObject對象實現了太多的方法,遠多於NSObject協議中定義的,例如:鍵值編碼,而有些時候你是不須要這些方法的。

When building a proxy object, the goal is generally to leave most methods unimplemented so that they can be forwarded in bulk using a method like forwardInvocation:. Subclassing NSObject would pull in a lot of baggage that would interfere. NSProxy helps to avoid this by giving you a simpler superclass that doesn't have so much extra stuff in it.
通常使用代理對象都是爲了保證大多數的方法不被實現,而是讓像 forwardInvocation: 這樣的方法去調用那些沒有實現的方法。相對NSProxy對象,NSObject子類對象老是要實現一些用不到的東西,反而感受妨礙了正常使用。NSProxy類經過提供一個簡單的父類,去掉多餘的部分,來防止了NSObject類的這種狀況。

參考:
     一、《Objective-C編程之道 iOS設計模式解析》第22章 代理

Protocols
協議

The fact that the NSObject protocol is useful for root classes isn't all that interesting for most Objective-C programming, since we don't use other root classes very often. However, it becomes really handy when making your own protocols. Say you have a protocol like this:
編寫Objective-C程序的時候,大多數時間都體會不到NSObject協議對根類帶來的用處,多是由於咱們不常用其餘根類的緣故。然而,當你開始編寫本身的協議時候,NSObject協議就變得很是有用了。假設你寫了一個這樣的協議:


@protocol MyProtocol - (void)foo; @end

And now you have a pointer to an object that conforms to it:
而且,你有一個遵循這個協議的對象:

id<MyProtocol> obj;

You can tell this object to foo:
你能夠向這個對象發送foo消息:

[obj foo];

However, you cannot ask the object for its description:
可是,你不可以向這個對象發送description消息:

[obj description]; // no such method in the protocol

And you can't check it for equality:
同上,你也不能向該對象發送isEqual:的消息:

[obj isEqual: obj2]; // no such method in the protocol

In general you can't ask it to do any of the stuff that a normal object can do. Sometimes this doesn't matter, but sometimes you actually want to be able to do this stuff.
通常來講,你不能要求 obj 作日常的對象能夠作的事情。有時這是無所謂的,可是有時你確實須要讓 obj 作日常的對象能夠作的那些事。

This is where the NSObject protocol Comes in. Protocols can inherit from other protocols. You can make MyProtocol inherit from the NSObject protocol:
這裏就是NSObject協議的用武之地了。協議能夠繼承自其餘的協議(s)。你可讓MyProtocal繼承自NSObject協議:

@protocol MyProtocol <NSObject> - (void)foo; @end

This says that not only do objects that conform to MyProtocol respond to -foo, but they also respond to all those common messages in the NSObjectprotocol. Since every object in your app typically inherits from the NSObject class and it conforms to the NSObject protocol, this doesn't impose any additional requirements on people implementing MyProtocol, while allowing you use these common methods on instances.
也就是說,不只能夠像遵循MyProtocol協議的對象能夠響應-foo消息,也能夠響應NSObject協議中定義的那些經常使用的消息。因爲在你的應用中的對象一般都繼承自NSObject類,又NSObject類遵循NSObject協議,所以,你不用在實現MyProtocol協議的時候作任何附加的事情就可使用這些經常使用的方法。

Conclusion
結尾

The fact that there are two different NSObjects  is an odd corner of the frameworks, but it makes sense when you get down to it. An NSObject  protocol allows multiple root classes to all have the same basic methods, and also makes it easy to declare a protocol which also includes basic functionality expected of any object. The NSObject  class conforms to the NSObject  protocol, bringing everything together.
在框架中,有兩個不一樣的NSObjects確實一件挺奇怪的事情,可是當你明白了上面說的以後,仍是頗有道理的。NSObject協議容許多個根類都具備相同的基本方法,也使聲明一個包括基本方法的協議變得很容易。NSObject類遵循NSObject協議,從而將一切融合在了一塊兒。 
相關文章
相關標籤/搜索