Nullability、__covariant、__contravariant,__kindof
来源:互联网 发布:淘宝实拍保护图片要求 编辑:程序博客网 时间:2024/06/03 21:37
1 Nullability
- nonnull :
- 不可为nil
- nullable
- 可以为nil
- null_resettable
- 表示 setter 可以为nil,但是 getter 不可以为nil
- __nullable
- 用来修饰一个变量,前面还要加双下划线
@property (nonatomic, strong, nonnull) Sark *sark;@property (nonatomic, copy, nullable) NSArray *friends;+ (nullable NSString *)friendWithName:(nonnull NSString *)name; @property (null_resettable, nonatomic, strong) UIView *view; - (void)startWithCompletionBlock:(nullable void (^)(NSError * __nullable error))block;
- Audited Regions
- Foundation 提供了一对儿宏,包在里面的对象默认加 nonnull 修饰符,只需要把 nullable 的指出来就行
NS_ASSUME_NONNULL_BEGIN@interface Sark : NSObject@property (nonatomic, copy, nullable) NSString *workingCompany;@property (nonatomic, copy) NSArray *friends;- (nullable NSString *)gayFriend;@endNS_ASSUME_NONNULL_END
总结:
Nullability 在编译器层面提供了空值的类型检查,在类型不符时给出 warning,方便开发者第一时间发现潜在问题。不过我想更大的意义在于能够更加清楚的描述接口,是主调者和被调者间的一个协议,比多少句文档描述都来得清晰,打个比方:
+ (nullable instancetype)URLWithString:(NSString *)URLString;
NSURL 的这个 API 前面加了 nullable 后,更加显式的指出了这个接口可能因为 URLString 的格式错误而创建失败,使用时自然而然的就考虑到了判空处理。
2 Lightweight Generics
- 带泛型的容器
- 可以指定容器类中对象的类型了
NSArray<NSString *> *strings = @[@"sun", @"yuan"];NSDictionary<NSString *, NSNumber *> *mapping = @{@"a": @1, @"b": @2};
- 自定义泛型类
- 这个类型在 @interface 和 @end 区间的作用域有效,可以把它作为入参、出参、甚至内部 NSArray 属性的泛型类型,我们还可以给 ObjectType 增加类型限制。若什么都不加,表示接受任意类型 ( id );当类型不满足时编译器将产生 error。对于
//这个 ObjectType(其他字符也可以) 是传入类型的 placeholder,它只能在 @interface 上定义(类声明、类扩展、Category)@interface Stack<ObjectType> : NSObject//入参- (void)pushObject:(ObjectType)object;//出参- (ObjectType)popObject;//内部 NSArray 属性的泛型类型@property (nonatomic, readonly) NSArray<ObjectType> *allObjects;@end
- 自定义泛型类带类型限制
- 我们还可以给 ObjectType 增加类型限制。若什么都不加,表示接受任意类型 ( id );当类型不满足时编译器将产生 error。
// 只接受 NSNumber * 的泛型@interface Stack<ObjectType: NSNumber *> : NSObject// 只接受满足 NSCopying 协议的泛型@interface Stack<ObjectType: id<NSCopying>> : NSObject//多参数的泛型,用逗号隔开,其他都一样,可以参考 NSDictionary 的头文件
总结:
@interface Stack<ObjectType: id<NSCopying>,keyObject:id<NSCopying>,myObject:NSString *> : NSObject-(void)pushObject:(ObjectType)object;-(myObject)popObject;@property (nonatomic,readonly)NSArray<ObjectType>*allObjects;@end
3 协变性和逆变性
当类支持泛型后,它们的 Type 发生了变化,比如下面三个对象看上去都是 Stack,但实际上属于三个 Type:
Stack *stack; // Stack *Stack<NSString *> *stringStack; // Stack<NSString *>Stack<NSMutableString *> *mutableStringStack; // Stack<NSMutableString *>
当其中两种类型做类型转化时,编译器需要知道哪些转化是允许的,哪些是禁止的,比如,默认情况下:
我们可以看到:
- 不指定泛型类型的 Stack 可以和任意泛型类型转化,
- 但指定了泛型类型后,两个不同类型间是不可以强转的
假如你希望主动控制转化关系,就需要使用泛型的协变性和逆变性修饰符了:
- __covariant
- 协变性,子类型可以强转到父类型(里氏替换原则)
- __contravariant
- 逆变性,父类型可以强转到子类型(WTF?)
协变性:
@interface Stack<__covariant ObjectType> : NSObject
效果:
NSString = NSMutableString
逆变:
@interface Stack<__contravariant ObjectType> : NSObject
效果:
NSMutableString = NSString
4 __kindof
- 明确表明了返回值,又让使用者不必写强转
。
没有__kindof之前:
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier; MyCell *tCell = (MyCell*)[tableview dequeueReusableCellWithIdentifier:@"cellID"];
有__kindof之后:
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; MyCell*tCell = [tableview dequeueReusableCellWithIdentifier:@"cellID"];
Where to go
有了上面介绍的这些新特性以及如 instancetype 这样的历史更新,Objective-C 这门古老语言的类型检测和类型推断终于有所长进,现在不论是接口还是代码中的 id 类型都越来越少,更多潜在的类型错误可以被编译器的静态检查发现。
同时,个人感觉新版的 Xcode 对继承链构造器的检测也加强了,NS_DESIGNATED_INITIALIZER 这个宏并不是新面孔,可以使用它标志出像 Swift 一样的指定构造器和便捷构造器
最后,附上一段用上了所有新特性的代码,Swift 是发展趋势,如果你暂时依然要写 Objective-C 代码,把所有新特性都用上,或许能让你到新语言的迁移更无痛一点。
原文:2015 Objective-C 新特性
0 0
- Nullability、__covariant、__contravariant,__kindof
- Xcode 7新的特性:Nullability,__kindof修饰符 _Nonlable, _Nonnull(温故知新,防止遗忘)
- Nullability Annotations
- Nullability Annotations
- Nullability Annotations
- ID,instancetype与__kindof
- __kindof 与 __typeof
- nonnull、泛型、__kindof
- OC 泛型, __kindof
- Nullability 和 Objective-C
- 编译器警告Nullability Annotations
- Nullability and Objective-C
- Nullability and Objective-C
- OC中__kindof的用法
- Swift Nullability and Objective-C
- Swift iOS中的Nullability Annotations
- null/nil以及Nullability Annotations
- iOS-泛型(nullable/null_resettable/__kindof用法)
- JSP自定义标签开发
- WINAPI *** SAL
- Javascript模块化编程:require.js的用法
- jdk8 安装及环境配置
- 环信 头像 昵称处理
- Nullability、__covariant、__contravariant,__kindof
- C#学习笔记之操作Access数据库
- 判断密码强弱的 js
- 全职猎人主题曲-太阳在夜晚依旧闪耀
- apache服务器搭建过程中需要注意到的一些问题
- Caffe错误:Message type "caffe.SolverParameter" has no field named "name"
- Android——TextView实现真正的跑马灯效果
- 【DSP开发】【Linux开发】Linux下PCI设备驱动程序开发
- Android微信支付的两大坑点