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

◇◆丶佛笑我妖孽 提交于 2019-12-03 13:22:56
原文链接: 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类的这种情况。

参考:
     1、《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协议,从而将一切融合在了一起。 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!