Objective-C 与 泛型
从 Xcode 7 开始,为了更简单和高效的与 Swift 交互, Objective-C
支持了引入了 3 个高级特性:轻量泛型、Nullability annotation、KindOf。
本文希望对 轻量泛型 做一个简单的介绍。更多信息,请参考 llvm 或者 与 Objective-C API 交互[1]
轻量泛型 是什么?
轻量泛型 可以让开发者执行集合类的类型信息,并且支持与 Swift
的泛型系统进行相互转化。
为什么使用 轻量泛型?
通常情况下,我们使用下面的语法声明数组:
代码语言:javascript复制NSArray *dates;
通过在类型后面添加 <NSDate *>
,我们可以告诉编译器:这个数组只接受 NSDate
类型的实例。
NSArray<NSDate *> *dates;
下面,我们通过实例验证一下它的作用:
代码语言:javascript复制NSArray<NSDate *> *dates;
NSString *str = dates[2];
当我们编译上述代码时,clang
在语法校验时会自动提示 ⚠️ 信息:NSDate
与 NSString
不兼容
image-20210105220623395
解决该 ⚠️ 的方案也很简单,把 NSString
换成 NSDate
即可。
NSDate *date = dates[2];
如何让自己的类支持 轻量泛型?
1、如下所示,声明类型时,开发者需要在 类名 后面新增一些typedef-names[2]
代码语言:javascript复制@interface NSCovariant1<T>
@interface NSCovariant1<T, U : NSObject *>
2、在实例方法或者类方法中,使用 T
代替普通的类型声明
- (void)setObject:(U)obj forKeyedSubscript:(T)key;
验证
下面,我们写一个完整的 Demo 对上面的功能进行验证:
代码语言:javascript复制// main.m
@import Foundation;
@interface KKMutableDictionary<KeyType, ObjectType> : NSObject
- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key;
@end
@implementation KKMutableDictionary
- (void)setObject:(nullable id)obj forKeyedSubscript:(id <NSCopying>)key {
}
@end
int main() {
KKMutableDictionary<NSString *, NSDate *> *dic = [KKMutableDictionary new];
dic[@"today"] = @"2021-01-01";
dic[@"today"] = [NSDate date];
dic[@"today"] = nil;
NSLog(@"%@", dic);
}
进行语法检测并打印语法树:
代码语言:javascript复制xcrun clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
1、语法检测会提示 dic[@"today"] = @"2021-01-01";
存在类型兼容问题。
image-20210105223501712
2、源码的第 5 行的语法树如下:
image-20210105223959567
我们简单对上面的语法树进行讲解:
ObjCInterfaceDecl
代表类的声明,本例中是KKMutableDictionary
- 随后,是父类
NSObject
- 最后是两个
ObjCTypeParamDecl
:KeyType
和ObjectTYpe
总结
本文分享了轻量泛型的用法,并通过 clang
命令将对应的语法树进行了介绍。
参考资料
[1]
与 Objective-C API 交互: https://github.com/949478479/Using-Swift-with-Cocoa-and-Objective-C-in-Chinese/blob/master/02-Interoperability/01-Interacting with Objective-C APIs.md#lightweight_generics
[2]
typedef-names: https://clang.llvm.org/doxygen/DeclObjC_8h_source.html#l00567