Swift有动态调度和虚拟方法吗?

Ian*_*ose 21 virtual-functions dynamic-dispatch swift

从C++/Java/C#背景开始我希望在Swift中看到虚拟方法,但是阅读swift文档我没有提到虚拟方法.

我错过了什么?

Jas*_*ues 17

与C++不同,没有必要指定方法在Swift中是虚拟的.编译器将确定以下哪项使用:

(性能指标当然取决于硬件)

  • 内联方法:0 ns
  • 静态调度:<1.1ns
  • 虚拟调度1.1ns(指定时为Java,C#或C++).
  • 动态调度4.9ns(如Objective-C).

Objective-C当然总是使用后者.4.9ns开销通常不是问题,因为这将占整个方法执行时间的一小部分.但是,必要时开发人员可以无缝地回退到C或C++.然而,在Swift中,编译器将分析哪个最快可以使用并尝试代表您做出决定,支持内联,静态和虚拟,但保留Objective-C互操作性的消息.可以标记一种dynamic鼓励消息传递的方法.

这样做的一个副作用是动态调度提供的一些强大功能可能无法使用,因为之前可以假设任何Objective-C方法都是如此.动态调度用于方法拦截,后者又用于:

  • 可可式的财产观察员.
  • CoreData模型对象检测.
  • 面向方面编程

上述功能的类型是late binding语言提供的功能.请注意,虽然Java使用vtable dispatch进行方法调用,但它仍然被认为是一种后期绑定语言,因此具有上述功能,因为它具有虚拟机和类加载器系统,这是提供运行时检测的另一种方法."Pure"Swift(没有Objective-C interop)就像C++一样,是一种带有静态调度的直接可执行编译语言,然后这些动态特性在运行时是不可能的.在ARC的传统中,我们可能会看到更多这类功能转向编译时间,这为"每瓦性能"提供了优势 - 这是移动计算中的一个重要考虑因素.

  • @nielsbot KVO 依赖于根据名称查找函数。那就是动态调度。因此,如果 Swift 使用 KVO,则它必须使用动态调度。这再次意味着它没有使用 vtable 查找,这就是所谓的“纯”swift。我认为我们应该处理纯 swift 的概念。ObjC 是 Swift 的自然组成部分。它的设计考虑到了 ObjC。它是斯威夫特 DNA 的一部分。 (2认同)
  • @greenoldman一般规则是:Swift偏爱静态种类(内联,静态,vtable)并将选择哪些是适当的,内联小体,静态如果没有子类,否则vtable.同时,如果类扩展NSObject或具有`@objc`指令,则使用消息传递,尽管在这些情况下可能仍然使用静态样式,我们可以通过将方法声明为`dynamic`来避免这种情况..相当复杂. (2认同)

tro*_*foe 5

所有方法都是虚拟的。但是,您需要声明要使用override关键字从基类覆盖方法:

从《Swift编程指南》中

覆写

子类可以提供自己的实例方法,类方法,实例属性或下标的自定义实现,否则该实例方法将从超类继承。这称为覆盖。

要覆盖原本会被继承的特征,请在覆盖定义的前面加上override关键字。这样做可以澄清您打算提供替代,并且没有错误地提供匹配的定义。意外覆盖可能会导致意外行为,并且override在编译代码时,任何没有关键字的覆盖都会被诊断为错误。

override关键字还提示斯威夫特编译器检查您的覆盖类的超(或父母中的一方)有符合您的覆盖提供的一个声明。此检查可确保您的替代定义正确。


joh*_*nyu -2

Swift 的目的是让 Objective-C 程序员能够轻松学习,而 Objective-C 中没有虚方法,至少不是你想象的那样。如果您在此处寻找有关如何在 Objective-C 中创建抽象类或虚拟方法的说明,通常它是一个仅引发异常并使应用程序崩溃的普通方法。(这有点道理,因为你不应该调用虚拟方法)

因此,如果 Swift 文档没有提及虚拟方法,我的猜测是,就像 Objective-C 中一样,没有虚拟方法。

  • 在 Swift 中没有必要显式指定一个方法为 virtual,编译器会决定是否: a) 内联 b) 使用静态分派(非虚拟) b) 使用 vtable 分派(如 Java) c) 使用动态分派,如 Objective -C 。。许多 Objective-C 老手都对 Swift 没有默认动态调度感到惊讶。 (2认同)