美文网首页
iOS 关键字和泛型

iOS 关键字和泛型

作者: 一片姜汁 | 来源:发表于2018-06-07 16:32 被阅读25次

    一.关键字

    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];
    

    相关文章

      网友评论

          本文标题:iOS 关键字和泛型

          本文链接:https://www.haomeiwen.com/subject/asvgsftx.html