为何Swift中Double原生类型可被识别为AnyObject却无法遵循要求AnyObject类型的协议?
为什么Swift中Double既被识别为AnyObject又无法遵循类协议?
这个看似矛盾的现象,其实是Swift的Objective-C桥接机制和类专属协议的本质要求之间的差异导致的,咱们拆开来理清楚:
1. 为什么Double能被识别为AnyObject?
Swift里的基本值类型(比如Double、Int、Bool)在和AnyObject交互时,会触发自动桥接机制:当你把Double转为AnyObject,或者用is AnyObject判断时,Swift会偷偷把这个值类型包装成对应的Objective-C类实例——这里Double会被包装成NSNumber(Objective-C里的数值类)。
因为NSNumber是标准的类类型(继承自NSObject,也就是AnyObject的底层实现之一),所以double is AnyObject会返回true,编译器也清楚这个桥接是必然发生的,才会提示警告说这个判断永远为真。
简单说:不是Double本身是AnyObject,而是它能被自动包装成一个AnyObject类型的实例。
2. 为什么Double无法遵循继承自AnyObject的协议?
当你定义protocol ClassProtocol: AnyObject { }时,这个协议就变成了类专属协议——它明确要求遵循它的类型必须是类类型(引用类型),而Double本质上是值类型,和类类型有着本质区别:
- 值类型是栈上存储的,赋值时会拷贝;
- 类类型是堆上存储的,赋值时传递引用。
哪怕Double能被桥接成NSNumber类实例,那也只是临时的包装,Double本身依然是值类型,不符合类专属协议对“类型本身是类”的要求,所以编译器会报错“非类类型无法遵循类协议”。
一句话总结
这两个场景并不矛盾:
- 第一个场景是Swift为了兼容Objective-C,给值类型提供了自动桥接成类实例的能力;
- 第二个场景是类专属协议的规则,它要求的是类型本身必须是类,而不是能被包装成类实例。
内容的提问来源于stack exchange,提问作者Ilias Karim
相关产品推荐
相关产品推荐

