有几种面向对象语言,可以定义新的根类,包括C++、PHP和Objto-C,它们工作得很好,所以这绝对不是一件特别的事情.
Objective-C有一个通用基类是有原因的
正如苏丹提到的,这不是事实.Objective-C中有多个根类,只需不指定超类,就可以定义一个新的根类.Sulthan还提到,可可本身有几个根类,NSObject
、NSProxy
和Object
(在ObjC 1.0中,根类为Protocol
).
原始Objto-C语言非常灵活,理论上有人可以创建自己的根类,并创建自己完全不同于基础的框架,并使用完全不同于retain
, release
, alloc
、dealloc
等的方法.如果他愿意,他甚至可以实现一种完全不同的内存管理方式.这种灵活性是裸Objective-C语言令人惊叹的地方之一——它只是提供了一个很薄的层,所有其他的事情,比如对象的创建和销毁,内存管理等等,都可以由位于顶层的用户框架来决定.
然而,有了Apple的Objective-C2.0和现代运行时,要创建自己的根类,需要完成more work个.随着ARC的加入,为了在ARC中使用对象,必须实现Cocoa的内存管理方法,如retain
和release
.此外,要在Cocoa集合中使用对象,类还必须实现isEqual:
和hash
之类的功能.
因此,在现代Cocoa/Cocoa Touch开发中,对象通常必须至少实现一组基本方法,即NSObject
协议中的方法.Cocoa(NSObject
NSProxy
)中的所有根类都实现了NSObject
协议.
那是怎么回事?是没有定义的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的Angular 来看,它实际上有一个名为SwiftObject
的超类.这个SwiftObject
类实现了NSObject
协议的方法,比如retain
、release
、isEqual:
、respondsToSelector:
等(尽管它实际上并不符合NSObject
协议).这就是如何将纯Swift对象与Cocoa API一起使用而不会出现问题.
然而,从Swift本身的内部来看,编译器并不认为Swift根类实现了这些方法.所以,如果你定义了一个根类Foo
,那么如果你试图调用Foo().isKindOfClass(Foo.self)
,它将不会编译它,抱怨这个方法不存在.但我们仍然可以使用它的技巧——回想一下,编译器将允许我们对AnyObject
类型的变量调用任何Objective-C方法(编译器听说过),方法查找会生成一个隐式展开的可选函数,该函数在运行时成功或失败.所以我们可以做的是将其转换为AnyObject
,确保导入Foundation
或ObjectiveC
(这样声明对编译器可见),然后我们可以调用它,它将在运行时工作:
(Foo() as AnyObject).isKindOfClass(Foo.self)
所以基本上,从Objective-C的Angular 来看,Swift类要么有一个现有的Objective-C类作为根类(如果它继承自Objective-C类),要么有SwiftObject
个作为根类.