文件上说

笔记

Swift类不会从通用基类继承.你呢

摘自:苹果公司"The Swift Programming Language."iBooks.

这对我来说没什么意义.Objective-C有一个通用基类是有原因的,同样的原因也应该适用于Swift,是吗?NSObject管理保留/释放语义,这是isEqual:hashdescription的默认实现.所有这些功能在Swift中也可用.

(Objective-C和Swift使用相同的运行时…)

那是怎么回事?没有定义超类的Swift类是否只有NSObject个,在引擎盖下充当适当的根类?还是每个新根类的默认对象行为都是重复的?还是他们创造了另一个Swift基类?retainrelease的实现非常复杂,因为它需要同时考虑多线程和弱引用.

Swift中是否有一个通用的基类(不管文档怎么说)?这真的很方便,因为在Objective-C中,我可以编写扩展,让我将方法调用合并到主runloop,比如[obj.eventually updateCounter],它可以作为"下次主运行循环控制时调用-updateCounter.如果在此期间,我再次调用此方法,则无论如何只应调用一次.通过此扩展,可以将-[UIView setNeedsDisplay]实现为[self.eventually display];.如果没有通用基类(或者可能是,谁知道呢?),这在Swift中不再可能实现."

推荐答案

有几种面向对象语言,可以定义新的根类,包括C++、PHP和Objto-C,它们工作得很好,所以这绝对不是一件特别的事情.

Objective-C有一个通用基类是有原因的

正如苏丹提到的,这不是事实.Objective-C中有多个根类,只需不指定超类,就可以定义一个新的根类.Sulthan还提到,可可本身有几个根类,NSObjectNSProxyObject(在ObjC 1.0中,根类为Protocol).

原始Objto-C语言非常灵活,理论上有人可以创建自己的根类,并创建自己完全不同于基础的框架,并使用完全不同于retain, release, allocdealloc等的方法.如果他愿意,他甚至可以实现一种完全不同的内存管理方式.这种灵活性是裸Objective-C语言令人惊叹的地方之一——它只是提供了一个很薄的层,所有其他的事情,比如对象的创建和销毁,内存管理等等,都可以由位于顶层的用户框架来决定.

然而,有了Apple的Objective-C2.0和现代运行时,要创建自己的根类,需要完成more work个.随着ARC的加入,为了在ARC中使用对象,必须实现Cocoa的内存管理方法,如retainrelease.此外,要在Cocoa集合中使用对象,类还必须实现isEqual:hash之类的功能.

因此,在现代Cocoa/Cocoa Touch开发中,对象通常必须至少实现一组基本方法,即NSObject协议中的方法.Cocoa(NSObjectNSProxy)中的所有根类都实现了NSObject协议.

那是怎么回事?是没有定义的Swift类

这是一个很好的问题,您可以通过使用Objective-C运行时进行内省来找到答案.Swift中的所有对象在某种意义上也是Objective-C对象,因为它们可以与Objective-C运行时一起使用,就像Objective-C中的对象一样.类中的一些成员(未标记为@objcdynamic的成员)可能对Objective-C不可见,但在其他方面,Objective-C运行时的所有内省功能都完全适用于纯Swift类的对象.在Swift中定义的类与Objective-C运行时中定义的任何其他类类似,只是名称有误.

使用Objective-C运行时,您可以发现,对于Swift中的根类,从Objective-C的Angular 来看,它实际上有一个名为SwiftObject的超类.这个SwiftObject类实现了NSObject协议的方法,比如retainreleaseisEqual:respondsToSelector:等(尽管它实际上并不符合NSObject协议).这就是如何将纯Swift对象与Cocoa API一起使用而不会出现问题.

然而,从Swift本身的内部来看,编译器并不认为Swift根类实现了这些方法.所以,如果你定义了一个根类Foo,那么如果你试图调用Foo().isKindOfClass(Foo.self),它将不会编译它,抱怨这个方法不存在.但我们仍然可以使用它的技巧——回想一下,编译器将允许我们对AnyObject类型的变量调用任何Objective-C方法(编译器听说过),方法查找会生成一个隐式展开的可选函数,该函数在运行时成功或失败.所以我们可以做的是将其转换为AnyObject,确保导入FoundationObjectiveC(这样声明对编译器可见),然后我们可以调用它,它将在运行时工作:

(Foo() as AnyObject).isKindOfClass(Foo.self)

所以基本上,从Objective-C的Angular 来看,Swift类要么有一个现有的Objective-C类作为根类(如果它继承自Objective-C类),要么有SwiftObject个作为根类.

Swift相关问答推荐

体积单位从夸脱转换为杯似乎关闭了

Swift C外部实现的Task / Future类类型

SwiftUI轨迹绘制怪异

RxSwift .debounce,.throttle用于分页

expose 不透明的底层类型

为什么 Swift URL 的 init?(string: String,relativeTo: URL?) 仅添加协议?

如何使用模型在 SwiftUI 的列表中进行搜索

如何在闭包中使用构造 await sync

快速递归:函数与闭包

RxSwift 中 Single.just(...) 和 Observable.just(...) 之间有区别吗?

SwiftUI:决定键盘重叠的内容

符合协议要求委托变量在 ios13 中可用

使用自定义相机拍照 iOS 11.0 Swift 4. 更新错误

否定 #available 语句

如何在Swift中找出字母是字母数字还是数字

如何从 UITableViewCell 类中引用 UITableViewController?

在 Swift 中覆盖 UIScrollView 的委托属性(就像 UICollectionView 一样)

如何在swift中的每N个字符处为字符串添加分隔符?

ld:入口点(_main)未定义.对于架构 x86_64:Xcode 9

在 IOS 项目中放置 .txt 文件并从中读取的位置