目录:
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<NSString *> *arr,数组里存放的都是字符串类型
2、类的泛型声明:
泛型声明:在声明类的时候,在类的后面<泛型名称>:@interface Person<ObjectType> : NSObject
泛型仅仅是报警告
泛型好处:1.从数组中取出来,可以使用点语法:数组中存放元素的类型为id类型, id是不能使用点语法,但是利用泛型,给其限制类型,则从数组中取出对象后,可以利用点语法
2.给数组添加元素,有提示
3、泛型在开发中使用场景:
1.用于限制集合类型:(集合类包括NSArray和NSSet,两者用法相同,前者是有序的,而后者却是无序的)
为什么集合可以使用泛型?使用泛型,必须要先声明泛型? => 如何声明泛型
自定义泛型?
什么时候使用泛型?
2: 在声明类的时候,不确定某些属性或者方法类型,在使用这个类的时候才确定,就可以采用泛型
自定义Person,会一些编程语言(iOS,Java),在声明Person,不确定这个人会什么,在使用Person才知道这个Person会什么语言
如果没有定义泛型.默认就是id
//声明:
#import <Foundation/Foundation.h>
@interface Person<ObjectType> : NSObject
// 语言
@property (nonatomic, strong) ObjectType language;
@end
//使用:
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
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<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
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
网友评论