当前位置: 首页 > 面试题库 >

为什么Swift中没有通用的基类?

苏嘉歆
2023-03-14
问题内容

该文件说

注意

Swift类不能从通用基类继承。您定义而未指定超类的类将自动成为您要构建的基类。”

摘录自:Apple Inc.“ Swift编程语言。” iBooks。

这对我来说没有多大意义。Objective-
C具有通用基类是有原因的,并且同样的原因也适用于Swift,是吗?NSObject管理着保留/释放语义,对默认的实现isEqual:hashdescription。所有这些功能在Swift中也可用。

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

那么,这是怎么回事?没有定义超类的Swift类是否只是NSObject在幕后构成适当的根类的?还是为每个新的根类重复默认的对象行为?还是他们创建了另一个Swift基类?的实施retainrelease是非常复杂的,因为它需要采取多线程和弱引用考虑在同一时间。

Swift中可能有一个通用的基类(尽管文档说了什么)?这真的很方便,因为在Objective-C中,我可以编写一些扩展,使我[obj.eventuallyupdateCounter]可以将方法调用合并到主运行循环中,例如可以将其读取为“-updateCounter下次主运行循环得到控制时调用。如果在此期间,我再次调用此方法,无论如何应该只调用一次,有了这个扩展,就可以实现,-[UIViewsetNeedsDisplay]因为[self.eventually display];如果没有通用基类(或者也许,谁知道,这在Swift中将不再可能)。


问题答案:

在几种面向对象的语言中,可以定义新的根类,包括C ++,PHP和Objective-C,它们可以正常工作,因此,这绝对不是什么特别的事情。

为什么Objective-C具有通用基类是有原因的

正如苏尔坦所说,这是不正确的。在Objective-
C中有多个根类,您可以通过不指定超类来定义新的根类。正如Sulthan还提到,可可本身具有若干根类,NSObjectNSProxy,和Object(根类的Protocol在ObjC
1.0)。

原来的Objective-
C语言是非常灵活的,有人在理论上可以一起走,创造了自己的根类,并创建自己的框架,从基础完全不同,使用方法完全不同retainreleaseallocdealloc,等,甚至可以如果他愿意,可以实现一种完全不同的内存管理方式。这种灵活性是裸露的Objective-
C语言如此令人惊奇的事情之一-它仅提供一个薄层,所有其他事情(如对象的创建和销毁方式,内存管理等)都可以由用户确定坐在上面的框架。

但是,使用Apple的Objective-C2.0和现代化的运行时,需要做更多的工作才能创建自己的根类。加上ARC,为了在ARC中使用对象,必须实现Cocoa的内存管理方法,例如retainrelease。另外,要在Cocoa集合中使用对象,您的类还必须实现isEqual:和这样的东西hash

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

那么,这是怎么回事?没有定义超类的Swift类仅仅是NSObjects,它们在后台构成了正确的根类吗?还是为每个新的根类重复默认的对象行为?还是他们创建了另一个Swift基类?

这是一个很好的问题,您可以通过自省使用Objective-C运行时来查找。从某种意义上说,Swift中的所有对象也是Objective-C对象,因为它们可以与Objective-C中的对象一起用于Objective-
C运行时。类的某些成员(未标记@objc或的成员dynamic)可能对Objective-C不可见,但否则,Objective-C运行时的所有自省功能将完全对纯Swift类的对象起作用。在Swift中定义的类看起来像在Objective-C运行时中的任何其他类,除了名称被修改。

通过使用Objective-C运行时,您可以发现,对于一个作为Swift中根类的类,从Objective-
C的角度来看,它实际上有一个名为的超类SwiftObject。而这个SwiftObject类实现的方法NSObject类似协议retainreleaseisEqual:respondsToSelector:,等(虽然它实际上并不符合NSObject协议)。这样便可以毫无问题地将纯Swift对象与Cocoa
API结合使用。

但是,从Swift本身内部,编译器并不认为Swift根类会实现这些方法。因此,如果您定义根类Foo,则尝试调用Foo().isKindOfClass(Foo.self),它会抱怨该方法不存在而不会对其进行编译。但是我们仍然可以使用它来技巧-回忆一下,编译器将让我们对type变量调用任何Objective-
C方法(编译器已经听说过)AnyObject,并且方法查找会产生一个隐式解包的可选函数,该函数在运行时成功或失败。因此,我们可以将其强制转换为AnyObject,确保导入FoundationObjectiveC(这样声明对编译器可见),然后可以调用它,它将在运行时运行:

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

因此,从Objective-C的角度来看,基本上,Swift类要么具有一个现有的Objective-C类作为根类(如果它是从Objective-C类继承的),要么具有一个SwiftObject根类。



 类似资料:
  • 我已经开始使用Spring WebFlux,最近我想知道为什么ServerResponse没有主体类型的泛型。这与同步响应不一致 ServerResponse中的响应体类型在此方法的签名中未知。是不是应该像下面这样? 我想知道ServerResponse没有这种泛型类型的原因是什么?

  • 问题内容: 我知道每次键入字符串文字时,字符串池中都会引用相同的String对象。 但是,为什么String API不包含,所以我可以使用引用? 至少,这将节省编译时间,因为编译器将知道引用现有的String,而不必检查是否已创建它以进行重用,对吗?我个人认为,字符串文字(尤其是很小的文字)在许多情况下是一种“代码异味”。 那么是否没有String.Empty背后的宏伟设计原因,还是语言创建者根本

  • 问题内容: 在Java中,有和接口。两者都属于Java的标准框架,并提供了一种访问元素的分类方法。 但是,据我了解没有。你可以用来对列表进行排序。 知道为什么要这样设计吗? 问题答案: 列表迭代器首先确保你以列表的内部顺序(也称为插入顺序)获取列表的元素。更具体地说,它是按照插入元素的顺序或操作列表的方式进行的。排序可以看作是对数据结构的一种操作,有几种方法可以对列表进行排序。 我将按照自己的见解

  • 问题内容: 为什么JavaFX中没有ObservableQueue?如果我们查看FXCollection的Java 9文档(只是看一下8的变化),我们会看到用于创建Observable集,列表和映射的静态助手方法。还有一些创建Observable float和integer数组的方法。但是,无法创建ObservableQueue。Java中的Queue接口具有许多有趣的实现,包括ArrayDequ

  • 问题内容: 我正在尝试做这样的事情: 不幸的是,即使在Java 9中也不存在。 为什么它被遗漏了? 建议的解决方法是什么? 问题答案: 为什么它被遗漏了? 该API提供了可重用的构建块。这里的相关积木是,,。通过这些,您可以实现所需的功能:将流内映射到对象,然后获得平面图。提供构建基块的排列是不切实际的,并且很难扩展。 建议的解决方法是什么? 如前所述,使用可用的构建基块(+ ):

  • 许多编译器都提供128位整数类型,但我使用过的编译器都没有提供typedefs。为什么? 据我回忆,标准 用于此目的的储量 鼓励提供此类类型的实现提供typedef 要求此类实现提供至少128位的intmax_t (而且,我不相信我使用了实际上符合最后一点的实现)