Swift本地基类或NSObject
我testing了一些与Swift混合的isa ,发现它只有在NSObject是一个超级类(直接或更高级)或者使用'@objc'装饰时才起作用。 否则,它将遵循静态和虚表分发风格,如C ++。
定义一个没有Cocoa / NSObject基类的Swift类是正常的吗? 如果是我所关心的,这意味着Objective-C的许多dynamic性,比如方法拦截和运行时自省。
dynamic运行时行为是属性观察者,核心数据, 面向方面编程 , 高级消息传递 ,分析和日志框架等function的核心。
使用Objective-C的方法调用样式可以将大约20个机器代码操作数添加到方法调用中,因此在某些情况下( 对具有小实体的方法进行多次严格的调用 ),C ++风格的静态调度和vtable调度可以更好地执行。
但是,考虑到一般的95-5规则( 性能增益的95%来自调整代码的5% ),从强大的dynamic特性开始并在必要时加强是不合理的?
Swift类是NSObject的子类:
- 是Objective-C类本身
- 使用
objc_msgSend()
调用(大部分)方法 - 为其大部分的方法实现提供Objective-C运行时元数据
Swift类不是NSObject的子类:
- 是Objective-C类,但只实现了一些NSObject兼容性的方法
- 不要使用
objc_msgSend()
来调用它们的方法(默认) - 不要为其方法实现提供Objective-C运行时元数据(默认情况下)
在Swift中使用NSObject可以获得Objective-C运行时的灵活性,而且还可以获得Objective-C的性能。 如果您不需要Objective-C的灵活性,避免NSObject可以提高性能。
编辑:
随着Xcode 6 beta 6,dynamic属性出现。 这允许我们指示Swift一个方法应该使用dynamic调度,因此将支持拦截。
public dynamic func foobar() -> AnyObject { }
我还发现,如果基于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你真的必须!
根据语言参考,没有要求类inheritance任何标准的根类,所以你可以根据需要包含或省略一个超类。
请注意,从类声明中省略超类,不会分配任何types的隐式基类超类。 它定义了一个基类,它将有效地成为一个独立的类层次结构的根。
从语言参考:
Swift类不会从通用基类inheritance。 你定义的类没有指定超类自动成为基础类,你要build立。
试图从没有超类(即基类)的类引用super
将导致编译时错误
'super' members cannot be referenced in a root class
我相信绝大多数Swift数据都不会是objc
。 只有那些需要与Objective C基础设施进行通信的部分才会被明确标记。
我不知道在哪个范围内将运行时反思添加到语言中。 如果方法明确允许的话,方法拦截可能会变得可能。 这是我的猜测,但是只有苹果公司的语言devise师才真正知道他们在哪里。
下面是从苹果的Swift电子书复制,并给出了一个适当的答案你的问题:
定义一个基类
任何不从另一个类inheritance的类都称为基类。
Swift类不会从通用基类inheritance。 你定义的类没有指定超类自动成为基础类,你要build立。
参考
这是正常的。 看看Swift的devise目标:目标是让大量的编程问题消失。 Swizzling方法可能不是你想要用Swift做的事情之一。