为什么要子类化 NSObject?
Objective-C 中 NSObject 的目的/用途是什么?我看到像这样扩展 NSObject 的类:
@interface Fraction : NSObject
在 C++ 或 Java 中,我们不使用任何像 NSObject 这样的变量,即使我们在 Objective-C 和 Java 中都有预处理器指令和 import 语句。
为什么 Objective-C 中的类显式继承自 NSObject?不声明继承自 NSObject 会有什么后果?
What is the purpose/use of NSObject in Objective-C? I see classes that extend NSObject like this:
@interface Fraction : NSObject
In C++ or Java, we don't use any variables like NSObject even though we have preprocessor directives and import statements in both Objective-C and Java.
Why do classes explicitly inherit from NSObject in Objective-C? What are the consequences of not declaring inheritance from NSObject?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我们使用 NSObject 来明确声明给定的类继承自什么。我不确定 C++,但在 Java 中有类似的东西 - Object 类。唯一的区别是 Java 不要求类显式从 Object 继承 - 该语言假定任何没有指定父类的东西都从 Object 继承。 Objective-C 是不同的,因为它允许您定义不同的根类 - 您可以创建一个不继承自 NSObject 的类。
这种不同根类的一个示例是
NSProxy
。看一下 GNUstep NSObject 源,它展示了方法如何通过 C 函数与 Objective-C 运行时交互。
We use NSObject to explicitly state what a given class inherits from. I'm not sure about C++, but in Java there's something similar - the Object class. The only difference is that Java doesn't require that classes explicitly descend from Object - the language assumes anything that doesn't have a specified parent class descends from Object. Objective-C is different because it allows you to define different root classes - you are allowed to make a class that doesn't inherit from NSObject.
An example of such a different root class is
NSProxy
.Have a look at the GNUstep NSObject source, it shows how the methods interact with the objective-c runtime through C functions.
由于面向对象语言具有继承的概念,因此在任何继承层次结构中都有一个根类。在 Java 中,默认父类(如果未提供)为
java.lang.Object
,而在 Objective-C 中,如果您没有显式声明父类,则不会获得父类。本质上,您的类本身就成为根类。这是 Objective-C 新手中的一个常见错误,因为在这种情况下您通常希望从 NSObject 继承。虽然经常出现问题和令人困惑,但这实际上提供了相当大的灵活性,因为您可以定义自己的类层次结构,其行为与 NSObject 完全不同。 (Java 根本不允许你这样做。)另一方面,除非你知道自己在做什么,否则很容易让自己陷入困境。幸运的是,如果您调用的方法不是由没有声明父类的类定义的,例如您通常希望从 NSObject 继承的方法,编译器将发出警告。
至于 NSObject 的“使用”,请查看 NSObject 的文档类和NSObject协议。它们定义了用于对象分配、内存管理、比较、散列、打印描述、检查类成员资格、查询对象是否响应选择器等的常用方法。基本上,NSObject“适合”提供 Objective-C 对象的核心功能免费。
Since object-oriented languages have the concept of an inheritance, in any inheritance hierarchy there is a root class. In Java, the default parent class (if none is provided) is
java.lang.Object
, whereas in Objective-C, if you don't explicitly declare a parent class, you don't get one. Essentially, your class becomes a root class itself. This is a common mistake among Objective-C newcomers, since you normally want to inherit from NSObject in such cases.While often problematic and puzzling, this actually allows quite a bit of flexibility, since you can define your own class hierarchies that act completely differently from NSObject. (Java doesn't allow you to do this at all.) On the other hand, unless you know what you're doing, it's easy to get yourself into trouble this way. Fortunately, the compiler will provide warnings if you call a method not defined by a class with no declared parent class, such as those you would normally expect to inherit from NSObject.
As for the "use" of NSObject, check out the documentation of the NSObject class and NSObject protocol. They define common methods used for object allocation, memory management, comparison, hashing, printing descriptions, checking class membership, querying whether objects respond to a selector, etc. Basically, NSObject is "good for" providing the core functionality of Objective-C objects free of charge.
所有类不一定都继承自 NSObject,但它是许多类的核心,因为它提供了分配、保留和释放等功能。
All classes don't necessarily inherit from NSObject but it is the core for many of the classes because it provides things like alloc, retain, and release.
NSObject 是所有类的根类。在我看来,它的 3 个最基本的功能是为您分配和初始化内存(alloc 和 init),以及提供描述函数。
Objective-C 的核心是对象向其他对象发送消息——因此 NSObject 的存在就是为了提供这种基本功能。
如果这对您来说听起来很奇怪,您可能希望阅读更多有关编程范式的内容,特别是面向对象编程……不过,简而言之,Objective C 是 C 语言的简单扩展。 C 使您能够对计算机内存、数字和字符进行编程,但执行其他任何操作(例如使用字符串或显示视图)时,您需要扩展部分,而 NSObject 是该扩展的开头。
选择一个类(例如 NSString 或任何与此相关的类),然后跟随它的超类回到 NSObject,以查看每个类添加了哪些功能,这可能是一个有用的练习。
希望有帮助...
NSObject is the root class of all classes. In my estimation, it's 3 most basic functions are to allocate and initialize memory for you (alloc & init), as well as provide a description function.
Objective-C is all about objects sending messages to other objects -- so NSObject exists to provide that basic functionality.
If this sounds strange to you, you may wish to read more about programming paradigms, particularly object-oriented programming....In a nutshell, however, Objective C is a simple extension to the C language. C gets you the ability to program computer memory, numbers, and characters, but do anything else (like use strings, or show views, for example) you need the extension part, and NSObject is the beginning of that extension.
It may be a useful exercise to pick a class (like NSString, or any for that matter), and follow it's superclasses back to NSObject, to see what functionality each class added.
Hope that helps...
来自Apple文档 - https://developer.apple.com/documentation/objectivec/nsobject。
基本上,大多数 OOP 编程语言显式或隐式指定基类或基功能。否则,您无法构建对象相互通信的系统。属性、内存管理、消息发送机制部分或全部由 NSObject 提供或支持。 Apple 提供部分 Objective-C 实现 - https://opensource.apple.com/source/objc4/objc4-723/runtime/NSObject.mm.auto.html,在这里可以看到 NSObject 内部的实际内容。
另外,因为 Objective-C 是 C 家族的语言,所以编译器和链接器需要计算如何在内存中布局对象以及放置和查找方法的位置,只有当您知道每个类/实例如何在内存中放置并且在哪里。对于 Objective-C,所有基类(NSObject、NSProxy 等)都有相关规范,因此可以计算它们的大小并在其上添加所有继承的内容 - https://clang.llvm.org/compatibility.html#objective-c。
因此,编译器不允许留下没有基类的类。所以最终类继承应该指向根类之一。如果您不指定它(来自 Xcode),则会出现以下错误:
From Apple documentation - https://developer.apple.com/documentation/objectivec/nsobject.
Basically, most of OOP programming languages explicitly or implicitly specify base class or base functionality. Otherwise you cannot build system where objects communicate with each other. Properties, memory management, message sending mechanism are partly or completely provided or supported by NSObject. Apple provide parts of the Objective-C implementation - https://opensource.apple.com/source/objc4/objc4-723/runtime/NSObject.mm.auto.html, where it's possible to see what is actually inside NSObject.
Also because Objective-C is a language from C-family, so compiler and linker needs to calculate how to layout object in memory and where put and find methods, that's only possible if you know how each of the classes/instances lays in memory and where. In case of Objective-C all base classes (NSObject, NSProxy, etc) have specification of that, so it's possible to calculate their size and add on top all inherited stuff - https://clang.llvm.org/compatibility.html#objective-c.
Consequently compiler don't let to leave a class without base class. So in the end class inheritance should lead to one of the root classes. Here is the error that appears if you don't specify it (from Xcode):