zoukankan      html  css  js  c++  java
  • ios开发ios9新特性关键字学习:泛型,逆变,协变,__kindof

    一:如何去学习?都去学习什么?

    1:学习优秀项目的设计思想,多问几个为什么,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中 2:学习优秀项目的代码风格,代码的封装设计思想,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中,每行代码都要用心去写,每一行代码都要力求使最简洁的

    3:学习别人遇到问题是如何分析问题,解决问题的方法是什么

    4:遇到新东西应该如何去学习:1:先研究要学习的东西作用是什么 ,有什么好处  2:如何使用:具体的语法知识 ,参照苹果的API 3:使用场景:一般在项目中有什么应用。

    5:最重要的就是花大量的时间研究优秀的代码,比别人想的深比别人想的远,注意每一个细节,把每一个细节都要搞懂,把每一个细节做到极致,花大量的时间去实践练习,将学习到的知识应用于项目中。

    二:nullable, nonnull,null_resettable,_Null_unspecified 的关键字的认识

    /* 1:介绍
        怎么去研究新特性? 1.使用新的xcode创建项目,用旧的xcode去打开
        Xcode7 2015 iOS9
        Xcode6 2014 iOS8
        Xcode5 2013 iOS7
        Xcode4 2012 iOS6
     
        1.出了哪些新特性 iOS9:关键字:可以用于属性,方法返回值和参数中
        关键字作用:提示作用,告诉开发者属性信息
        关键字目的:迎合swift,swift是个强语言,swift必须要指定一个对象是否为空
        关键字好处:提高代码规划,减少沟通成本
        关键字仅仅是提供警告,并不会报编译错误
     */
    
    /* 2:nullable:
        nullable:1.怎么使用(语法) 2.什么时候使用(作用)
        nullable作用:可能为空
     
        nullable 语法1
        @property (nonatomic, strong, nullable) NSString *name;
     
        nullable 语法2 * 关键字 变量名
        @property (nonatomic, strong) NSString * _Nullable name;
     
        nullable 语法3
        @property (nonatomic, strong) NSString * __nullable name;
     
     */
    
    /* 3:nonnull
     nonnull:1.怎么使用(语法) 2.什么时候使用(作用)
     nonnull作用:不能为空
     
     nonnull 语法1
     @property (nonatomic, strong, nullable) NSString *name;
     
     nonnull 语法2 * 关键字 变量名
     @property (nonatomic, strong) NSString * _Nonnull name;
     
     nonnull 语法3
     @property (nonatomic, strong) NSString * __nonnull name;
     
     */
    
    /*
     4:null_resettable:
     
     null_resettable:1.怎么使用(语法) 2.什么时候使用(作用)
     
     null_resettable:必须要处理为nil情况,重写get方法
     
     null_resettable作用:get方法不能返回nil,set可以传入为空
     
     null_resettable 语法1
     @property (nonatomic, strong, null_resettable) NSString *name;
     
     
     - (NSString *)name
     {
     if (_name == nil) {
     _name = @"";
     }
     return _name;
     }
    
     
     */
    
    /*
         5:_Null_unspecified:不确定是否为空
     */
    
    /*
     6:
        1:关键字注意点
        在NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END之间默认是nonnull,一般前者写在头文件之下,后者写在end之上
        
        2:关键字不能用于基本数据类型(int,float),nil只用于对象
     
        3: @property (nonatomic) NSString *name;如此写法,默认为strong修饰的
     */
    
    #import "ViewController.h"
    
    @interface ViewController ()
    
    // nonnull
    // 没有处理为空的情况
    @property (nonatomic, strong, nonnull)NSString  *name;
    
    @end
    
    @implementation ViewController
    
    //- (UIView *)view
    //{
    //    if (_view == nil) {
    //        [self loadView];
    //        [self viewDidLoad];
    //    }
    //    return _view
    //}
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
    }
    
    
    @end

    三:泛型

    #import "ViewController.h"
    
    /*
       1:泛型介绍
     
        泛型:限制类型 
        为什么要推出泛型?迎合swift
        泛型作用:1.限制类型 2.提高代码规划,减少沟通成本,一看就知道集合中是什么东西
        泛型定义用法:类型<限制类型>:NSMutableArray<NSString *> *arr,数组里存放的都是字符串类型
     
       2:类的泛型声明:
     
        泛型声明:在声明类的时候,在类的后面<泛型名称>:@interface Person<ObjectType> : NSObject
        泛型仅仅是报警告
        泛型好处:1.从数组中取出来,可以使用点语法:数组中存放元素的类型为id类型, id是不能使用点语法,但是利用泛型,给其限制类型,则从数组中取出对象后,可以利用点语法
                2.给数组添加元素,有提示
        
       3: 泛型在开发中使用场景:
     
        1.用于限制集合类型:(集合类包括NSArray和NSSet,两者用法相同,前者是有序的,而后者却是无序的)
     
        为什么集合可以使用泛型?使用泛型,必须要先声明泛型? => 如何声明泛型
        自定义泛型?
        什么时候使用泛型?
        
         2: 在声明类的时候,不确定某些属性或者方法类型,在使用这个类的时候才确定,就可以采用泛型
     
        自定义Person,会一些编程语言(iOS,Java),在声明Person,不确定这个人会什么,在使用Person才知道这个Person会什么语言
         如果没有定义泛型.默认就是id
     
        例如:
     
     1;声明泛型
       #import <Foundation/Foundation.h>
     
        @interface Person<ObjectType> : NSObject
     
         // 语言
        @property (nonatomic, strong) ObjectType language;
     
        
        @end
     
     
     2:使用:
         
     Java *java = [[Java alloc] init];
     iOS *ios = [[iOS alloc] init];
     
     // iOS
     Person<iOS *> *p = [[Person alloc] init];
     p.language = ios;
     
     // Java
     Person<Java *> *p1 = [[Person alloc] init];
     p1.language = java;
    
     */
    
    #import "Person.h"
    #import "Java.h"
    #import "iOS.h"
    @interface ViewController ()
    
    @property (nonatomic, strong) NSMutableArray<NSString *> *arr;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        Java *java = [[Java alloc] init];
        iOS *ios = [[iOS alloc] init];
        
        // iOS
        Person<iOS *> *p = [[Person alloc] init];
        p.language = ios;
        
        // Java
        Person<Java *> *p1 = [[Person alloc] init];
        p1.language = java;
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        
    }
    
    @end

    四:泛型的协变和逆变

    #import "ViewController.h"
    
    /*  1:
        泛型:限制类型 
        为什么要推出泛型?迎合swift
     
        泛型作用:1.限制类型 2.提高代码规划,减少沟通成本,一看就知道集合中是什么东西
        泛型定义用法:类型<限制类型>
        泛型声明:在声明类的时候,在类的后面<泛型名称>
        泛型仅仅是报警告
        泛型好处:1.从数组中取出来,可以使用点语法
                2.给数组添加元素,有提示
        
        泛型在开发中使用场景:1.用于限制集合类型
     
        id是不能使用点语法
     
        为什么集合可以使用泛型?使用泛型,必须要先声明泛型? => 如何声明泛型
     
        自定义泛型?
        什么时候使用泛型?在声明类的时候,不确定某些属性或者方法类型,在使用这个类的时候才确定,就可以采用泛型
     
        自定义Person,会一些编程语言(iOS,Java),在声明Person,不确定这个人会什么,在使用Person才知道这个Person会什么语言
        如果没有定义泛型.默认就是id
     
     
        用于父子类型转换
        泛型:__covariant:协变, 子类转父类 :也就是将子类的指针赋值给子类
     
            __contravariant:逆变 父类转子类:也就是将父类的指针赋值给子类
     
        泛型注意点:在数组中,一般用可变数组添加方法,泛型才会生效,如果使用不可变数组,添加元素,泛型没有效果,只是提示的作用
     
    
       2:继承:子类继承父类后,父类可在.h中暴露方法例如初始化方法供子类去继承 1:父类只暴露了初始化方法没有重写,子类继承后,子类可以重写,(子类在重写时,尽量用self,不要用类名,避免其他类在继承该类的时候,初始化得到的都是该类的对象,而不是继承的子类的对象。)那么子类重写后,在父类中的self就为子类的对象,其中多个子类继承同一个父类的时候,父类可以提供一个get的标识方法供子类重写返回标识,从而在父类中来区分不同的子类 2:父类提供方法,供子类继承,父类在实现该方法,则子类在外部调用初始化方法的时候,就会调用父类中实现的初始化方法。(新浪参数模型抽父类继承的例子),若是子类又重写父类的初始化方法,调用super会执行父类的方法,否则就不会执行父类的方法,会覆盖掉父类的方法,只保留子类的方法
     
     */
    
    #import "Person.h"
    #import "Java.h"
    #import "iOS.h"
    @interface ViewController ()
    
    @property (nonatomic, strong) NSMutableArray<NSString *> *arr;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [_arr addObject:@"123"];
    //    _arr = @[@"213",@"213",@1];
        // Do any additional setup after loading the view, typically from a nib.
        
        iOS *ios = [[iOS alloc] init];
        Language *language = [[Language alloc] init];
        
        // 父类转子类
        Person<Language *> *p = [[Person alloc] init];
        p.language = language;
        
        // iOS
        Person<iOS *> *p1 = [[Person alloc] init];
        p1 = p;
        
        
    }
    // 子类转父类
    - (void)covariant
    {
        iOS *ios = [[iOS alloc] init];
        Language *language = [[Language alloc] init];
        // iOS
        Person<iOS *> *p = [[Person alloc] init];
        p.language = ios;
        
        // Language
        Person<Language *> *p1;
        p1 = p;
    
    }
    
    - (void)test
    {
        Java *java = [[Java alloc] init];
        iOS *ios = [[iOS alloc] init];
        
        // iOS
        Person<iOS *> *p = [[Person alloc] init];
        p.language = ios;
        
        // Java
        Person<Java *> *p1 = [[Person alloc] init];
        p1.language = java;
    
    }
    
    @end

    五:__kindof

    #import "ViewController.h"
    #import "SubPerson.h"
    
    /*
        kindof:相当于
     
        __kindof:表示当前类或者它的子类',
     
        类设计历史
     
        id:可以调用任何对象方法,可以作为参数或是返回值,不能进行编译检查
        instancetype:自动识别当前类的对象,只能作为返回值不能作为参数,自动返回与当前类类型相同的对象
     */
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        /**
         *    当父类提供初始化的方法的时候,子类继承了父类的方法,若是子类SubPerson调用父类的初始化方法:person,则返回的是父类对象的类型,会出现警告,这时,可以在父类中定义的初始化方法用__kindof来修饰,表示当前类或是其子类。+ (__kindof Person *)person;
    
         */
         SubPerson *p = [SubPerson person];
        
    }
    
    @end
  • 相关阅读:
    android 本地字符串存取
    2020-07-17:线上一个服务有4个实例突然变得访问很慢,你会从什么地方入手找原因?
    2020-07-16:如何获得一个链表的倒数第n个元素?
    2020-07-15:死锁与活锁的区别,死锁与饥饿的区别?
    2020-07-14:es用过冷热分离吗?假如现在有些数据热变冷,有些数据冷变热,怎么解决?
    2020-07-28:已知sqrt (2)约等于 1.414,要求不用数学库,求sqrt (2)精确到小数点后 10 位。
    2020-07-29:从 innodb 的索引结构分析,为什么索引的 key 长度不能太长?
    2020-07-27:如何设计一个分布式文件系统,如何设计动态扩容和数据定位?
    2020-07-26:如何用 socket 编程实现 ftp 协议?
    2020-07-25:如何实现一个高效的单向链表逆序输出?
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5868702.html
Copyright © 2011-2022 走看看