一.关键字
1.NS_ASSUME_NONNULL_BEGIN 和 NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_BEGIN
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *address;
NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END包裹的属性代表这些属性是非空的,如果传入空值,系统会有警告。
屏幕快照 2018-06-07 下午4.01.28.png
2.null_resettable
@property (nonatomic,copy,null_resettable) NSString *name;
null_resettable关键字修饰的属性 Getter方法的返回值不可以为空 但是Setter方法可以为空,并且如果使用null_resettable修饰属性,必须重写属性的Getter 或者 Setter方法处理值为空的情况。否则会出现如下警告:
屏幕快照 2018-06-07 下午4.21.04.png
在Getter方法中处理值为空的情况(Setter中处理也行)
- (NSString *)name {
if (!_name) {
_name = @"默认值";
}
return _name;
}
_Null_unspecified表明属性不确定是否为空.png
二.OC中泛型
1.自定义泛型
新建一个Person类
#import <Foundation/Foundation.h>
@interface Person<ObjectType> : NSObject
@property (nonatomic,strong) ObjectType skill;
@end
调用【已经提前定义了IosProgramming和JavaProgramming两个类 代表ios编程和java编程】
//如果不指定泛型 skill的setter类型为id类型 传入任何值均可
Person *persion = [[Person alloc] init];
persion.skill = @"测试";
//指定泛型为IosProgramming 则skill的setter方法只可以传IosProgramming类的对象
Person <IosProgramming *>*persion = [[Person alloc] init];
persion.skill = [IosProgramming new];
//指定泛型为JavaProgramming 则skill的setter方法只可以传JavaProgramming类的对象
Person <JavaProgramming *>*persion = [[Person alloc] init];
persion.skill = [JavaProgramming new];
2.__covariant(协变)、__contravariant(逆变)
__covariant(协变):用于泛型中的强转类型,表明泛型可以向上强转,子类可以转成父类。
__contravariant(逆变):用于泛型中的强转类型,表明泛型可以向下强转,父类可以转成子类。
新建一个Person类
#import <Foundation/Foundation.h>
@interface Person<ObjectType> : NSObject
@property (nonatomic,strong) ObjectType skill;
@end
新建Language、IOS类,Language是IOS的父类
Language类
#import <Foundation/Foundation.h>
@interface Language : NSObject
@end
IOS类
#import "Language.h"
@interface IOS : Language
@end
1.运行下列代码【子类转父类】:
Person<Language *> *p_language = [Person new];
Person <IOS *>*p_ios = [Person new];
//将p_ios赋值给p_language系统会发出类型不一致的警告
p_language = p_ios;
解决办法:
指定Person的泛型为协变的:
#import <Foundation/Foundation.h>
@interface Person<__covariant ObjectType> : NSObject
@property (nonatomic,strong) ObjectType skill;
@end
2.运行下列代码【父类转子类】:
Person<Language *> *p_language = [Person new];
Person <IOS *>*p_ios = [Person new];
//将p_language赋值给p_ios系统会发出类型不一致的警告
p_ios = p_language;
解决办法:
指定Person的泛型为逆变的:
#import <Foundation/Foundation.h>
@interface Person<__contravariant ObjectType> : NSObject
@property (nonatomic,strong) ObjectType skill;
@end
3.__kindof
__kindof 表明返回值类型是当前类或者当前类的子类。
定义一个Person和Son类,Person是Son的子类。在Person中定义一个类方法,用于快速创建Person对象。
id修饰返回值类型
定义类方法
#import <Foundation/Foundation.h>
@interface Person : NSObject
+ (id)person;
@end
编译下列代码,并没有提示类型错误。
NSString *son = [Person person];
1.用id修饰返回值类型,不会在编译时进行类型判断。
2.返回值类型没有确切提示。
Person修饰返回值类型
定义类方法
#import <Foundation/Foundation.h>
@interface Person : NSObject
+ (Person *)person;
@end
编译下列代码,提示类型不一致。
Son *son = [Son person];
1.用类名修饰返回值类型,子类调用父类的方法,不会自动识别类型。
instancetype修改返回值类型
定义类方法
#import <Foundation/Foundation.h>
@interface Person : NSObject
+ (Person *)person;
@end
编译下列代码,类型不一致的警告消除。
Son *son = [Son person];
1.虽然会自动识别当前对象的类,但是仍然没有类型提示。
__kindof Person * 修饰返回值类型
定义类方法
#import <Foundation/Foundation.h>
@interface Person : NSObject
+ (__kindof Person *)person;
@end
编译下列代码,此时不仅会自动识别当前对象的类,而且也会有类型提示。
Son *son = [Son person];
网友评论