该文件说
注意 Swift类不能从通用基类继承。您定义而未指定超类的类将自动成为您要构建的基类。” 摘录自:Apple Inc.“ Swift编程语言。” iBooks。
注意
Swift类不能从通用基类继承。您定义而未指定超类的类将自动成为您要构建的基类。”
摘录自:Apple Inc.“ Swift编程语言。” iBooks。
这对我来说没有多大意义。Objective- C具有通用基类是有原因的,并且同样的原因也适用于Swift,是吗?NSObject管理着保留/释放语义,对默认的实现isEqual:,hash和description。所有这些功能在Swift中也可用。
NSObject
isEqual:
hash
description
(Objective-C和Swift使用相同的运行时…)
那么,这是怎么回事?没有定义超类的Swift类是否只是NSObject在幕后构成适当的根类的?还是为每个新的根类重复默认的对象行为?还是他们创建了另一个Swift基类?的实施retain和release是非常复杂的,因为它需要采取多线程和弱引用考虑在同一时间。
retain
release
Swift中可能有一个通用的基类(尽管文档说了什么)?这真的很方便,因为在Objective-C中,我可以编写一些扩展,使我[obj.eventuallyupdateCounter]可以将方法调用合并到主运行循环中,例如可以将其读取为“-updateCounter下次主运行循环得到控制时调用。如果在此期间,我再次调用此方法,无论如何应该只调用一次,有了这个扩展,就可以实现,-[UIViewsetNeedsDisplay]因为[self.eventually display];如果没有通用基类(或者也许,谁知道,这在Swift中将不再可能)。
[obj.eventuallyupdateCounter]
-updateCounter
-[UIViewsetNeedsDisplay]
[self.eventually display];
在几种面向对象的语言中,可以定义新的根类,包括C ++,PHP和Objective-C,它们可以正常工作,因此,这绝对不是什么特别的事情。
为什么Objective-C具有通用基类是有原因的
正如苏尔坦所说,这是不正确的。在Objective- C中有多个根类,您可以通过不指定超类来定义新的根类。正如Sulthan还提到,可可本身具有若干根类,NSObject,NSProxy,和Object(根类的Protocol在ObjC 1.0)。
NSProxy
Object
Protocol
原来的Objective- C语言是非常灵活的,有人在理论上可以一起走,创造了自己的根类,并创建自己的框架,从基础完全不同,使用方法完全不同retain,release,alloc,dealloc,等,甚至可以如果他愿意,可以实现一种完全不同的内存管理方式。这种灵活性是裸露的Objective- C语言如此令人惊奇的事情之一-它仅提供一个薄层,所有其他事情(如对象的创建和销毁方式,内存管理等)都可以由用户确定坐在上面的框架。
alloc
dealloc
但是,使用Apple的Objective-C2.0和现代化的运行时,需要做更多的工作才能创建自己的根类。加上ARC,为了在ARC中使用对象,必须实现Cocoa的内存管理方法,例如retain和release。另外,要在Cocoa集合中使用对象,您的类还必须实现isEqual:和这样的东西hash。
因此,在现代的Cocoa / CocoaTouch开发中,对象通常至少必须实现一组基本方法,即NSObject协议中的方法。Cocoa(NSObject,NSProxy)中的所有根类均实现该NSObject协议。
那么,这是怎么回事?没有定义超类的Swift类仅仅是NSObjects,它们在后台构成了正确的根类吗?还是为每个新的根类重复默认的对象行为?还是他们创建了另一个Swift基类?
这是一个很好的问题,您可以通过自省使用Objective-C运行时来查找。从某种意义上说,Swift中的所有对象也是Objective-C对象,因为它们可以与Objective-C中的对象一起用于Objective- C运行时。类的某些成员(未标记@objc或的成员dynamic)可能对Objective-C不可见,但否则,Objective-C运行时的所有自省功能将完全对纯Swift类的对象起作用。在Swift中定义的类看起来像在Objective-C运行时中的任何其他类,除了名称被修改。
@objc
dynamic
通过使用Objective-C运行时,您可以发现,对于一个作为Swift中根类的类,从Objective- C的角度来看,它实际上有一个名为的超类SwiftObject。而这个SwiftObject类实现的方法NSObject类似协议retain,release,isEqual:,respondsToSelector:,等(虽然它实际上并不符合NSObject协议)。这样便可以毫无问题地将纯Swift对象与Cocoa API结合使用。
SwiftObject
respondsToSelector:
但是,从Swift本身内部,编译器并不认为Swift根类会实现这些方法。因此,如果您定义根类Foo,则尝试调用时Foo().isKindOfClass(Foo.self),它会抱怨该方法不存在而不会对其进行编译。但是我们仍然可以使用它来技巧-回忆一下,编译器将让我们对type变量调用任何Objective- C方法(编译器已经听说过)AnyObject,并且方法查找会产生一个隐式解包的可选函数,该函数在运行时成功或失败。因此,我们可以将其强制转换为AnyObject,确保导入Foundation或ObjectiveC(这样声明对编译器可见),然后可以调用它,它将在运行时运行:
Foo
Foo().isKindOfClass(Foo.self)
AnyObject
Foundation
ObjectiveC
(Foo() as AnyObject).isKindOfClass(Foo.self)
因此,从Objective-C的角度来看,基本上,Swift类要么具有一个现有的Objective-C类作为根类(如果它是从Objective-C类继承的),要么具有一个SwiftObject根类。