我用Swift测试了一些isa swizzling,发现它只适用于NSObject是超类(直接或更高级),或者使用' @ objc'装饰。否则它将遵循静态和vtable-dispatch样式,如C ++。
在没有Cocoa / NSObject基类的情况下定义Swift类是否正常?如果它是我所关心的,这意味着要超越Objective-C的大部分动力,例如方法拦截和运行时内省。
动态运行时行为是财产观察者,核心数据,Aspect Oriented Programming,Higher Order Messaging,分析和&等功能的核心。日志框架等。
使用Objective-C的方法调用样式会在方法调用中添加大约20个机器代码操作数,因此在某些情况下(对具有小型主体的方法的许多严格调用)C ++样式静态和vtable调度可以更好地执行。
但是考虑到一般的95-5规则( 95%的性能增益来自调整5%的代码),从强大的动态功能开始并没有意义必要时变硬吗?
答案 0 :(得分:98)
作为NSObject的子类的Swift类:
objc_msgSend()
来调用(大部分)他们的方法不是NSObject的子类的Swift类:
objc_msgSend()
来调用其方法(默认情况下)在Swift中对NSObject进行子类化可以获得Objective-C运行时灵活性以及Objective-C性能。如果您不需要Objective-C的灵活性,避免使用NSObject可以提高性能。
修改强>
使用Xcode 6 beta 6,会出现动态属性。这允许我们指示Swift方法应该使用动态分派,因此将支持拦截。
public dynamic func foobar() -> AnyObject {
}
答案 1 :(得分:13)
我还发现,如果在NSObject上建立Swift类,我会看到一些意外的运行时行为,可能会隐藏编码错误。这是一个例子。
在这个例子中,我们不基于NSObject,编译器正确地发现了testIncorrect_CompilerShouldSpot中的错误, 报告" ...' MyClass'不能兑换为MirrorDisposition'"
class MyClass {
let mString = "Test"
func getAsString() -> String {
return mString
}
func testIncorrect_CompilerShouldSpot() {
var myString = "Compare to me"
var myObject = MyClass()
if (myObject == myString) {
// Do something
}
}
func testCorrect_CorrectlyWritten() {
var myString = "Compare to me"
var myObject = MyClass()
if (myObject.getAsString() == myString) {
// Do something
}
}
}
在这个基于 NSObject 的示例中,编译器没有发现testIncorrect_CompilerShouldSpot中的错误:
class myClass : NSObject {
let mString = "Test"
func getAsString() -> String {
return mString
}
func testIncorrect_CompilerShouldSpot() {
var myString = "Compare to me"
var myObject = MyClass()
if (myObject == myString) {
// Do something
}
}
func testCorrect_CorrectlyWritten() {
var myString = "Compare to me"
var myObject = MyClass()
if (myObject.getAsString() == myString) {
// Do something
}
}
}
我认为道德是,只有你真正需要的NSObject!
答案 2 :(得分:12)
根据语言参考,不要求类继承任何标准根类,因此您可以根据需要包含或省略超类。
请注意,省略类声明中的超类,不会分配任何类型的隐式基类。它定义了一个基类,它将有效地成为独立类层次结构的根。
来自语言参考:
Swift类不从通用基类继承。给你上课 定义而不指定超类自动成为基类 你可以上课。
尝试从没有超类(即基类)的类中引用super
将导致编译时错误
'super' members cannot be referenced in a root class
答案 3 :(得分:1)
我相信绝大多数Swift数据都不会是objc
。只有那些需要与Objective C基础架构进行通信的部分才会明确标记为这样。
我不知道运行时内省会在何种程度上添加到语言中。只有在方法明确允许的情况下,方法拦截才有可能实现。这是我的猜测,但只有Apple内部的语言设计师才真正了解他们的目标。
答案 4 :(得分:1)
以下内容是从Apple的Swift-eBook中复制而来,并为您的问题提供了合适的答案:
任何不从其他类继承的类都称为基类。
Swift类不从通用基类继承。您定义的类而不指定超类会自动成为您构建的基类。
答案 5 :(得分:-6)
这很正常。看看Swift的设计目标:目标是让大量的编程问题消失。方法调配可能不是你想用Swift做的事情之一。