Swift - 自省

程序设计和人类哲学锁面临的同一个很重大的课题就是解决“我是谁”这个问题。在哲学里,这个问题属于自我认知的范畴,而在程序设计中,这个问题涉及自省(Introspection)。

向一个对象询问它是不是属于某个类。常用的方法有下面两类:

[obj isKindOfClass:[NSObject class]];
[obj isMemberOfClass:[NSObject class]];
  • - isKindOfClass: 判断obj 是否是NSObject 或者其子类的实例对象
  • - isMemberOfClass: 对obj 做出判断,当且仅当obj 的类型为NSObject 时返回为真。

这两个方法时NSObject 的方法,所以如果在Swift 中写的是NSObject 或其子类的话,直接使用这两个方法时没有任何问题的:

class ClassA: NSObject {}
class ClassB: ClassA {}

let obj1 = ClassB()
let obj2 = ClassB()
        
obj1.isKind(of: ClassA.self) // true
obj2.isMember(of: ClassA.self) // false

关于.self 的用法,我们在“AnyClass、元类型和.self”中已经有所提及,这里就不再重复了。

Objective-C几乎所有的类都会是NSObject 的子类,而在Swift 的世界中,从性能方面考虑,只要有可能,我们应该更倾向于选择那些非NSObject 子类的Swift 原生类型。
对于那些不是NSObject 的类,我们应该怎么确定其类型呢?

首先需要明确的一点是,我们为什么要在运行时去确定类型。因为有泛型支持,Swift 对类型的推断和记录是完备的。因此在绝大多数情况下,我们使用的Swift 类型都应该是在编译期间确定的。如果在你写的代码中经常需要检查和确定AnyObject到底是什么类的话,几乎就意味着你的代码设计出了问题(或者你正在写一些充满各种“小技巧”的代码)。虽然没有太多的意义,但是我们还是可以做这件事情:

class ClassA {}
class ClassB: ClassA {}

let obj1: AnyObject = ClassB()
let obj2: AnyObject = ClassB()
        
obj1.isKind(of: ClassA.self) // true
obj2.isMember(of: ClassA.self) // false

在Swift 中,AnyObject 应用最多的地方应该就是原来那些返回idCocoa API 了。

为了快速确定类型,Swift 提供了一个简洁的写法:对于一个不确定的类型,我们现在可以使用is 来进行判断is 在功能上相当于原来的isKindOfClass,可以检查一个对象是否属于某类型或其子类型is 和原来的区别主要在于两点:

  • 首先它不仅可以用于class 类型,也可以对Swift 的其他如structenum 等类型进行判断。它在实际使用中是这个样子的:
class ClassA {}
class ClassB: ClassA {}

let obj: AnyObject = ClassB()
        
if obj is ClassA {
    print("属于 ClassA")
}
if obj is ClassB  {
    print("属于 ClassB")
}
  • 另外,编译器将对这种检查进行必要性判断:如果编译器能够唯一确定的类型,那么is 的判断就没有必要,编译器将会抛出一个警告,类似这样的代码:
let string = "String"
if string is String {
    // Do something
}

// 'is' test is always true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值