问题描述
我已经阅读了一些关于 this one 之类的帖子,关于两者之间的区别在 Swift 中对 NSObject
进行子类化,或者只是拥有它的原生基础 class
而没有子类化.不过都是有点老的帖子了,这个话题我不是很清楚.
I have read some posts like this one about the difference between subclassing NSObject
in Swift or just having its native base class
with no subclassing. But they all are a bit old posts, and I am not clear about this topic.
什么时候应该继承NSObject
?子类化和不子类化之间的实际区别是什么?目前 Swift 中的推荐是什么?
When should you subclass NSObject
? What is the actual difference between subclassing it and not subclassing? What is currently the recommendation in Swift?
推荐答案
Apple 关于 NSObject 的文档 声明以下内容作为介绍:
Apple's documentation about NSObject states the following as an introduction:
NSObject 是大多数 Objective-C 类层次结构的根类.通过 NSObject,对象继承了运行时系统的基本接口以及作为 Objective-C 对象行为的能力.
正如这表明的那样,只要该类型的实例需要表现得像一个 Objective-C 对象(或类本身,在一些罕见的情况下),您需要为代码中引入的类型创建子类).
As this would suggest, you need to subclass NSObject for types introduced in your code whenever instances of that type need to behave like an Objective-C object (or the class itself, in some rarer cases).
我不知道 Apple 提供了关于何时不子类化 NSObject 的书面指导,超出了 建议减少动态调度 或使用不依赖于子类化但协议 扩展,即代码重用通常更静态调度和值类型友好).我相信可以公平地说,尽管大多数 Swift 程序员都从 Apple 那里得到了提示,并且在没有上述需求时,Swift 语言特性作为避免引入基于 NSObject 的类型的标志.也就是说,作为一般规则,只有在您真正需要 Objective-C 动态时才引入基于 NSObject 的类型,最常见的是当您需要与 Cocoa API 交互时(尤其是当您的代码与 UI 相关时:例如视图控制器,视图).
I am not aware of super explicit Apple provided written guidance on when not to subclass NSObject, beyond suggesting reducing dynamic dispatch or presenting code reuse paradigms using that do not relying on subclassing but protocol extensions, i.e. code reuse that is generally more static dispatch and value type friendly). I believe it is fair to say though that most Swift programmers have taken hints from Apple, and Swift language features as signs to avoid introducing NSObject based types when the above-mentioned need is not there. That is, as a general rule, only introduce NSObject based types when you actually need the Objective-C dynamism, most commonly when you need to interface with Cocoa APIs (especially common when your code is UI related: e.g. view controllers, views).
正如您链接到的问题的回答中所指出的,具有 Objective-C 风格的活力 介绍了基于objc_msgSend
的方法调度的性能.尽管 Swift 类中的方法也是虚拟的,但当您没有使用 @objc
属性显式标记方法时,编译器能够使用更快的方法分派方法——尤其是当 整个模块优化处于开启状态,在 Swift 3 中更是如此,其中 默认情况下,类不为超出模块的子类化而打开定义类型.
As pointed out in an answer to the question you link to, with Objective-C style dynamism comes the performance of objc_msgSend
based method dispatch. Although methods in Swift classes are also virtual, the compiler is able to use faster means of dispatching methods when you don't explicitly mark the methods with the @objc
attribute – especially when Whole Module Optimization is toggled on, and even more so in Swift 3 where classes are not by default open for subclassing beyond the module that defines the type.
除了避免使用 NSObject,您还可以在编写 Swift 时完全避免基于类的引用类型在许多情况下.看看例如上面链接的值类型 WWDC 视频,或者例如 这篇博文 作为介绍.简而言之,使用值类型可以获得良好的局部推理,通常可以避免动态内存分配和引用计数开销(尽管并非普遍如此 - 需要注意的是将引用类型作为字段的结构).
Beyond avoiding NSObject, you can also avoid class based reference types altogether in many cases when writing Swift. Take a look at for instance the value type WWDC videos linked above, or for example this blog post as an introduction. Briefly, using value types you gain good local reasoning, often avoid dynamic memory allocation and reference counting overhead (though not universally so – structs with reference types as fields being the caveat).
这篇关于Swift 3:是否继承 NSObject?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!