ios关键字、泛型

目录:

1关键字

1、nonnull:不能为空(用来修饰属性,或者方法的参数,方法的返回值)

 //三种使用方式都可以
@property (nonatomic, copy, nonnull) NSString *name;
@property (nonatomic, copy) NSString * _Nonnull name;
@property (nonatomic, copy) NSString * __nonnull name;
 
// 不适用于assign属性,因为它是专门用来修饰指针的
 @property (nonatomic, assign) NSUInteger age;

//补充(用下面宏包裹起来的属性全部都具nonnull特征,当然,如果其中某个属性你不希望有这个特征,也可以自己定义,比如加个nullable)
 //在NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END之间,定义的所有对象属性和方法默认都是nonnull
可以在定义方法的时候使用
//返回值和参数都不能为空
- (nonnull NSString *)test1:(nonnull NSString *)name;
- (NSString * _Nonnull)test2:(NSString * _Nonnull)name;

ios系统使用这个属性的很少、个人觉得了解一下即可。

2、nullable:表示可以为空

//三种使用方式
@property (nonatomic, copy, nullable) NSString *name;
@property (nonatomic, copy) NSString *_Nullable name;
@property (nonatomic, copy) NSString *__nullable name;

使用这个属性的时候,Xcode的代码提示会告诉你这个属性是可以为空的,算是一种编程规范吧,减少程序员之间的交流。

3、null_resettable: 必须处理为空的情况,重写set方法

@property (nonatomic, copy, null_resettable) NSString *name; 

- (void)setName:(NSString *)name {
     if (name == nil) {
         name = @"dong";
     }
    _name = name;
}

4、_Null_unspecified:不确定是否为空

@property (nonatomic, strong) NSString *_Null_unspecified name;
@property (nonatomic, strong) NSString *__null_unspecified name;

提高规范,减少沟通交流,如果违反规定xcode会报出警告供程序员修改、

2 泛型

1、泛型介绍

泛型:限制类型 
为什么要推出泛型?迎合swift
泛型作用:1.限制类型 2.提高代码规划,减少沟通成本,一看就知道集合中是什么东西
泛型定义用法:类型<限制类型>:NSMutableArray *arr,数组里存放的都是字符串类型

2、类的泛型声明:

泛型声明:在声明类的时候,在类的后面<泛型名称>:@interface Person : NSObject
泛型仅仅是报警告
泛型好处:1.从数组中取出来,可以使用点语法:数组中存放元素的类型为id类型, id是不能使用点语法,但是利用泛型,给其限制类型,则从数组中取出对象后,可以利用点语法
        2.给数组添加元素,有提示

3、泛型在开发中使用场景:

1.用于限制集合类型:(集合类包括NSArray和NSSet,两者用法相同,前者是有序的,而后者却是无序的)
为什么集合可以使用泛型?使用泛型,必须要先声明泛型? => 如何声明泛型
自定义泛型?

什么时候使用泛型?
2: 在声明类的时候,不确定某些属性或者方法类型,在使用这个类的时候才确定,就可以采用泛型
自定义Person,会一些编程语言(iOS,Java),在声明Person,不确定这个人会什么,在使用Person才知道这个Person会什么语言
 如果没有定义泛型.默认就是id
//声明:
#import 
@interface Person : NSObject
// 语言
@property (nonatomic, strong) ObjectType language;
@end
//使用:
 Java *java = [[Java alloc] init];
 iOS *ios = [[iOS alloc] init];

 // iOS
 Person *p = [[Person alloc] init];
 p.language = ios;

 // Java
 Person *p1 = [[Person alloc] init];
 p1.language = java; */
#import "Person.h"
#import "Java.h"
#import "iOS.h"
@interface ViewController ()

@property (nonatomic, strong) NSMutableArray *arr; @end

@implementation ViewController - (void)viewDidLoad {
    [super viewDidLoad];
    Java *java = [[Java alloc] init];
    iOS *ios = [[iOS alloc] init]; // iOS
    Person *p = [[Person alloc] init];
    p.language = ios; // Java
    Person *p1 = [[Person alloc] init];
    p1.language = java;
} 
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event {

} 
@end

4、泛型的协变和逆变
泛型:
    __covariant:协变, 子类转父类 :也就是将子类的指针赋值给父类
    __contravariant:逆变 父类转子类:也就是将父类的指针赋值给子类

泛型注意点:
    在数组中,一般用可变数组添加方法,泛型才会生效,如果使用不可变数组,添加元素,泛型没有效果,只是提示的作用

继承:
    子类继承父类后,父类可在.h中暴露方法例如初始化方法供子类去继承
1:父类只暴露了初始化方法没有重写,子类继承后,子类可以重写,(子类在重写时,尽量用self,不要用类名,避免其他类在继承该类的时候,初始化得到的都是该类的对象,而不是继承的子类的对象。)那么子类重写后,在父类中的self就为子类的对象,其中多个子类继承同一个父类的时候,父类可以提供一个get的标识方法供子类重写返回标识,从而在父类中来区分不同的子类
2:父类提供方法,供子类继承,父类在实现该方法,则子类在外部调用初始化方法的时候,就会调用父类中实现的初始化方法。若是子类又重写父类的初始化方法,调用super会执行父类的方法,否则就不会执行父类的方法,会覆盖掉父类的方法,只保留子类的方法

#import "ViewController.h"
#import "Person.h"
#import "Java.h"
#import "iOS.h"
@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *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 *p = [[Person alloc] init];
    p.language = language; // iOS
    Person *p1 = [[Person alloc] init];
    p1 = p;

} 

// 子类转父类
- (void)covariant {
    iOS *ios = [[iOS alloc] init];
    Language *language = [[Language alloc] init]; // iOS
    Person *p = [[Person alloc] init];
    p.language = ios; // Language
    Person *p1;
    p1 = p;

} 

- (void)test {
    Java *java = [[Java alloc] init];
    iOS *ios = [[iOS alloc] init]; // iOS
    Person *p = [[Person alloc] init];
    p.language = ios; // Java
    Person *p1 = [[Person alloc] init];
    p1.language = java;

}
@end

5、__kindof
__kindof:表示当前类或者它的子类

#import "ViewController.h"
#import "SubPerson.h"

@interface ViewController () 
@end

@implementation ViewController
 - (void)viewDidLoad {
    [super viewDidLoad]; 
    /**
    当父类提供初始化的方法的时候,子类继承了父类的方法,
    若是子类SubPerson调用父类的初始化方法:person,
    则返回的是父类对象的类型,会出现警告,
    这时,可以在父类中定义的初始化方法用__kindof来修饰,
    表示当前类或是其子类。+ (__kindof Person *)person; 
    */
 SubPerson *p = [SubPerson person];
} 
@end

参考文章

你可能感兴趣的:(ios关键字、泛型)