new方法的实现原理、构造方法、类工厂方法、instancetype和id

来源:互联网 发布:淘宝发货地与实际不符 编辑:程序博客网 时间:2024/04/29 08:20

一、new方法的实现原理
1.开辟存储空间,调用 + alloc 方法
2.初始化所有的属性(成员变量),调用 - init 方法
3.返回对象的地址
注意: alloc返回的地址, 和init返回的地址是同一个地址
二、alloc做了什么?
1.开辟存储空间
2.将所有的属性设置为0
3.返回当前实例对象的地址
三、init做了什么?
1.初始化成员变量, 但是默认情况下init的实现是什么都没有做,但是必须调用这个方法,这是规定!
2.返回初始化后的实例对象地址
四、构造方法
在OC中init开头的方法, 我们称之为构造方法,自定义的构造方法必须以init开头,且用驼峰命名法。
构造方法的用途: 用于初始化一个对象, 让某个对象一创建出来就拥有某些属性和值
重写init方法注意:
1.必须先初始化父类, 再初始化子类
2.必须判断父类是否初始化成功, 只有父类初始化成功才能继续初始化子类
3.返回当前对象的地址
4.格式
- (instancetype)init
{
if (self = [super init]) {
// 初始化子类
}
return self;
}
五、类工厂方法
自定义类工厂方法是苹果的一个规范, 一般情况下, 我们会给一个类提供自定义构造方法和自定义类工厂方法用于创建一个对象。
1.什么是类工厂方法:
用于快速创建对象的类方法, 我们称之为类工厂方法
类工厂方法中主要用于:给对象分配存储空间和初始化这块存储空间
2.规范:
(1).一定是类方法 +
(2).方法名称以类的名称开头, 首字母小写
(3).一定有返回值, 返回值是id/instancetype
(4).注意: 以后但凡自定义类工厂方法, 在类工厂方法中创建对象一定不要使用类名来创建,一定要使用self来创建,self在类方法中就代表类对象, 到底代表哪一个类对象呢?谁调用当前方法, self就代表谁.
(5).格式如下:
+ (instancetype)person
{
return [[Person alloc] init];
}
+ (instancetype)personWithAge:(int)age
{
Person *p = [[Person alloc] init];
p.age = age;
return p;
}
六、构造方法和类工厂方法的使用

#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic,copy) NSString *name;- (instancetype)initWithName:(NSString *)name;+ (instancetype)personWithName:(NSString *)name;@end----------#import "Person.h"@implementation Person- (instancetype)initWithName:(NSString *)name {  if (self = [super init]) {    _name = name;  }  return self;}+ (instancetype)personWithName:(NSString *)name {  return [[self alloc]initWithName:name];}@end----------#import <Foundation/Foundation.h>#import "Person.h"@interface Student : Person@property (nonatomic,copy) NSString *no;- (instancetype)initWithName:(NSString *)name no:(NSString *)no;+ (instancetype)studentWithName:(NSString *)name no:(NSString *)no;@end----------#import "Student.h"@implementation Student- (instancetype)initWithName:(NSString *)name no:(NSString *)no {  if (self = [super initWithName:name]) {    self.no = no;  }  return self;}+ (instancetype)studentWithName:(NSString *)name no:(NSString *)no {  return [[self alloc] initWithName:name no:no];;}@end

七、instancetype和id区别
1.id
(1).id是一个数据类型, 并且是一个动态数据类型
既然是数据类型, 所以就可以用来
(a).定义变量
(b).作为函数的参数
(c).作为函数的返回值
(2).默认情况下所有的数据类型都是静态数据类型
A.静态数据类型的特点:
(a).在编译时就知道变量的类型,
(b).知道变量中有哪些属性和方法
(c).在编译的时候就可以访问这些属性和方法,
(d).并且如果是通过静态数据类型定义变量, 如果访问了不属于静态数据类型的属性和方法, 那么编译器就会报错
B.动态数据类型的特点:
(a).在编译的时候编译器并不知道变量的真实类型, 只有在运行的时候才知道它的真实类型
(b).并且如果通过动态数据类型定义变量, 如果访问了不属于动态数据类型的属性和方法, 编译器不会报错
(3).id == NSObject * 万能指针
id和NSObject *的区别:
(a).NSObject *是一个静态数据类型
(b).id 是一个动态数据类型
(4).补充
(a).通过静态数据类型定义变量, 不能调用子类特有的方法
(b).通过动态数据类型定义变量, 可以调用子类特有的方法
(c).通过动态数据类型定义的变量, 可以调用私有方法
(d).弊端: 由于动态数据类型可以调用任意方法, 所以有可能调用到不属于自己的方法, 而编译时又不会报错, 所以可能导致运行时的错误
(e).应用场景: 多态, 可以减少代码量, 避免调用子类特有的方法需要强制类型转换
(f).为了避免动态数据类型引发的运行时的错误, 一般情况下如果使用动态数据类型定义一个变量, 在调用这个对象的方法之前会进行一次判断, 判断当前对象是否能够调用这个方法;isKindOfClass:方法判断指定的对象是否是某一个类, 或者是某一个类的子类;isMemberOfClass:方法判断指定的对象是否是当前指定的类的实例
2. instancetype
instancetype == id == 万能指针 == 指向一个对象
与id区别:
id在编译的时候不能判断对象的真实类型
instancetype在编译的时候可以判断对象的真实类型
id可以用来定义变量, 可以作为返回值, 可以作为形参
instancetype只能用于作为返回值
注意: 以后但凡自定义构造方法, 返回值尽量使用instancetype, 不要使用id

0 0
原创粉丝点击