OC基础--构造方法 id类型
new方法实现原理:
new做了三件事情
1.开辟存储空间 + alloc 方法
2.初始化所有的属性(成员变量) - init 方法
3.返回对象的地址
[Person new]; == [[Person alloc] init];
alloc: 1.开辟存储空间 2.将所有的属性设置为0 3.返回当前实例对象的地址
init: 1.初始化成员变量, 但是默认情况下init的实现是什么都没有做 2.返回初始化后的实例对象地址
注意: alloc返回的地址, 和init返回的地址是同一个地址
构造方法的概念及用途:
在OC中init开头的方法, 我们称之为构造方法
用于初始化一个对象, 让某个对象一创建出来就拥有某些属性和值
重写init方法, 在init方法中初始化成员变量:
重写init方法必须按照苹果规定的格式重写, 如果不按照规定会引发一些未知的错误
1.必须先初始化父类, 再初始化子类
子类继承自父类 那么子类拥有父类所有成员 子类必须调用父类的构造方法对这些成员进行初始化
2.必须判断父类是否初始化成功, 只有父类初始化成功才能继续初始化子类
为了防止父类的初始化方法release掉了self指向的空间并重新alloc了一块空间。还有[super init]可能alloc失败,这时就不再执行if中的语句
3.返回当前对象的地址
super 和 self 指向的是相同的消息接收者 即谁调用就代表谁
- (instancetype)init
{
// 1.初始化父类 只要父类初始化成功 , 就会返回对应的地址, 如果初始化失败, 就会返回nil nil == 0 == 假 == 没有初始化成功
self = [super init];
// 2.判断父类是否初始化成功
if (self != nil) {
// 3.初始化子类 设置属性的值
_age = ;
}
// 4.返回地址
return self;
}
简版:
- (instancetype)init
{
// 注意: 不要把 = 号写为 == 一定要将[super init]的返回值赋值给self
if (self = [super init]) {
// 初始化子类
_age = ;
}
return self;
}
自定义构造方法:
自定义构造方法 其实就是自定义一个init方法:
1.一定是对象方法
2.一定返回id/instancetype
3.方法名称一定以init开头
#import "Person.h" @implementation Person
// 重写init方法
- (instancetype)init{
if (self = [super init]) {
self.name = @"王二小";
self.age = ;
}
return self;
}
// 自定义构造方法 一个类可以有0个或者多个自定义构造方法
- (instancetype)initWithName:(NSString *)name{
if (self = [super init]) {
_name = name;
}
return self;
}
// 自定义构造方法可以有1个或多个参数
- (instancetype)initWithName:(NSString *) name andAge:(int) age{
if (self = [super init]) {
_name = name;
_age = age;
}
return self;
}
@end
自定义构造方法在继承中得表现:
谁声明的成员就由谁去初始化(父类的属性交给父类去处理 子类方法只处理自己独有的属性)
#import "Student.h" @implementation Student
/*
- (instancetype)initWithStudentNO:(NSString *)studentNO andName:(NSString *)name andAge:(int)age{
if (self = [super init]) {
self.name = name;
self.age = age;
self.studentNO = studentNO;
}
return self;
}
*/
- (instancetype)initWithStudentNO:(NSString *)studentNO andName:(NSString *)name andAge:(int)age{
// 由父类的构造方法去初始化 name 和 age 属性
if (self = [super initWithName:name andAge:age]) {
_studentNO = studentNO;
}
return self;
}
@end
调用图解:
自定义类工厂方法:
什么是类工厂方法:
用于快速创建对象的类方法, 我们称之为类工厂方法
类工厂方法中主要用于 给对象分配存储空间和初始化这块存储空间
自定义类工厂方法是苹果的一个规范, 一般情况下, 我们会给一个类提供自定义构造方法和自定义类工厂方法用于创建一个对象
规范:
1.一定是类方法 +
2.方法名称以类的名称开头, 首字母小写
3.一定有返回值, 返回值是id/instancetype
举例:
[[NSString alloc] init];
[NSString string]; [[NSString alloc] initWithString:(NSString *)];
[NSString stringWithString:(NSString *)]; [[NSArray alloc] init];
[NSArray array]; [NSArray alloc] initWithObjects:(id), ..., nil];
[NSArray arrayWithObjects:(id), ..., nil]; // 自定义类工厂方法
+ (instancetype)personWithName:(NSString *)name andAge:(int)age{
Person * person = [[Person alloc] init];
person.name = name;
person.age = age;
return person;
}
自定义类工厂方法在继承中注意点:
由于子类默认会继承父类所有的方法和属性, 所以类工厂方法也会被继承
在类工厂方法中创建对象一定不要使用类名来创建 一定要使用self来创建
self在类方法中就代表类对象 (谁调用当前方法, self就代表谁)
父类的类工厂方法创建实例对象时是使用父类的类名创建的, 如果子类调用父类的类工厂方法创建实例对象,创建出来的还是父类的实例对象
@interface Person : NSObject
+ (id)person;
@end @implementation Person
+ (id)person
{
return [[Person alloc] init];
}
@end @interface Student : Person
@property NSString *name;
@end @implementation Student
@end int main(int argc, const char * argv[])
{
Student *stu = [Student person];// 等效于 [[Person alloc] init] 需要该为 [[self alloc] init]
[stu setName:@"lnj"]; // 报错, 因为Person中没有setName
} // 自定义类工厂方法 使用self 而不是 类名
+ (instancetype)personWithName:(NSString *)name andAge:(int)age{
// Person * person = [[Person alloc] init];
Person * person = [[self alloc] init];
person.name = name;
person.age = age;
return person;
}
id类型:
id是一个数据类型, 并且是一个动态数据类型
既然是数据类型, 所以就可以用来
1.定义变量
2.作为函数的参数
3.作为函数的返回值
id == NSObject * 万能指针
id和NSObject *的区别:
NSObject *是一个静态数据类型
id 是一个动态数据类型
默认情况下所有的数据类型都是静态数据类型
静态数据类型的特点:
在编译时就知道变量的类型,
知道变量中有哪些属性和方法
在编译的时候就可以访问这些属性和方法,
如果是通过静态数据类型定义变量, 如果访问不了属于静态数据类型的属性和方法, 那么编译器就会报错
动态数据类型的特点:
在编译的时候编译器并不知道变量的真实类型, 只有在运行的时候才知道它的真实类型
如果通过动态数据类型定义变量, 如果访问了不属于动态数据类型的属性和方法, 编译器不会报错
- 通过静态数据类型定义变量, 不能调用子类特有的方法
- 通过动态数据类型定义变量, 可以调用子类特有的方法
- 通过动态数据类型定义的变量, 可以调用私有方法
- 弊端: 由于动态数据类型可以调用任意方法, 所以有可能调用到不属于自己的方法, 而编译时又不会报错, 所以可能导致运行时的错误
- 应用场景: 多态, 可以减少代码量, 避免调用子类特有的方法需要强制类型转换
- 为了避免动态数据类型引发的运行时的错误, 一般情况下如果使用动态数据类型定义一个变量, 在调用这个对象的方法之前会进行一次判断, 判断当前对象是否能够调用这个方法
- isKindOfClass
id obj = [Student new];
// isKindOfClass , 判断指定的对象是否是某一个类, 或者是某一个类的子类
if ([obj isKindOfClass:[Student class]]) {
[obj eat];
}
- isMemberOfClass
id obj = [Student new];
if ([obj isMemberOfClass:[Student class]]) {
// isMemberOfClass : 判断指定的对象是否是当前指定的类的实例
[obj eat];
}
instancetype和id的区别:
instancetype == id == 万能指针 == 指向一个对象
id在编译的时候不能判断对象的真实类型
instancetype在编译的时候可以判断对象的真实类型
(一个在编译时不知道真实类型, 一个在编译时知道真实类型)
id可以用来定义变量, 可以作为返回值, 可以作为形参
instancetype只能用于作为返回值
它会进行类型检查,如果创建出来的对象,赋值了不相干的对象就会有一个警告信息,防止出错
注意: 以后但凡自定义构造方法, 返回值尽量使用instancetype, 不要使用id
OC基础--构造方法 id类型的更多相关文章
- 关于void*类型的用法(相当于OC中的id类型)
关于void*类型的用法(相当于OC中的id类型) 1.C++语言在对于void* 类型的使用很特别,因为void* 可以间接引用任何其他数据类型的指针,比如int*.float*甚至抽象数据类型的指 ...
- 六.OC基础--1. id和instancetype类型,2.动态类型检测,3.响应方法,构造方法,4.重写构造方法,5.自定义构造方法
1. id和instancetype类型, id和instancetype类型区别: 1. id和instancetype都可以用来作为方法的返回值 2. id可以用来定义类型,instancetyp ...
- OC基础--构造方法
OC语言中类的构造方法学了两种: 一.方法一:[类名 new] 例:[Person new] 缺点:可扩展性不强,假如在Person类中有_age 成员变量,在初始化时想让_age 中的值为20,ne ...
- oc 中的id类型与类型转换
id是oc语言中一个独特的数据类型.一种通用对象类型.可以转换为任何数据类型,即id类型的变量可以存放任何数据类型的对象. 使用示例: Animal * dog = [[Dog alloc]init] ...
- OC基础笔记目录
OC基础(1) Objective-C简介 OC和C对比 第一个OC程序 面向对象思想 OC基础(2) 类与对象 类的设计 第一个OC类 对象方法的声明和实现 类方法的声明和实现 OC基础(3) 对象 ...
- 张超超OC基础回顾_05 property修饰符,id类型,instancetype。。。
一.property 如果给一个属性同时提供了getter/setter方法, 那么我们称这个属性为可读可写属性 如果只提供了getter方法, 那么我们称这个属性为只读属性 如果只提供了setter ...
- OC基础6:多态、动态类型和动态绑定
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.关于SEL类型的数据: (1).SEL ...
- OC的特有语法-分类Category、 类的本质、description方法、SEL、NSLog输出增强、点语法、变量作用域、@property @synthesize关键字、Id、OC语言构造方法
一. 分类-Category 1. 基本用途:Category 分类是OC特有的语言,依赖于类. ➢ 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式 ● 继承 ● 分类(Categor ...
- 五.OC基础--1.多态,2.类对象,3.点语法,4.@property&@synthesize,5.动态类型,内省(判断对象是否遵循特定的协议,以及是否可以响应特定的消息)
五.OC基础--1.多态, 1. 多态概念,定义:多态就是某一类事物的多种形态: 表现形式: Animal *ani = [Dog new]; 多态条件:1.有继承关系 2.有方法的重写 2.多态代码 ...
随机推荐
- provider 设计模式
相关介绍文章: Provider Model Design Pattern and Specification, Part 1 (old but detailed). The ASP.NET 2.0 ...
- pinpoint 安装部署
.markdown-preview:not([data-use-github-style]) { padding: 2em; font-size: 1.2em; color: rgb(171, 178 ...
- (十六)getsockname()
简述: 获取一个套接口的本地名字. #include <winsock.h> int PASCAL FAR getsockname( SOCKET s, struct sockaddr F ...
- A*算法 -- 八数码问题和传教士过河问题的代码实现
前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...
- goroutine
Go语言从诞生到普及已经三年了,先行者大都是Web开发的背景,也有了一些普及型的书籍,可系统开发背景的人在学习这些书籍的时候,总有语焉不详的感觉,网上也有若干流传甚广的文章,可其中或多或少总有些与事实 ...
- PHP Cookie Session
这些都是基础知识,不过有必要做深入了解.先简单介绍一下. 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择, 都纪 ...
- arm cache line,PLD指令
C中嵌入汇编PLD指令:asm("PLD [%0,#128]": :"r" (psrc) ); copy自官方文档: 4.2.7. PLD.PLDW 和 PLI ...
- SQL Server Reporting Service(SSRS) 第四篇 SSRS 用法总结
1. 如何让表头在每页显示(译) A. 打开高级模式: 在分组栏中点击Column Goups右侧的箭头选择高级模式; B. 找到第一个Static组 在Row Groups区域中(注意不是Colu ...
- [经验] 新版SkyIAR、Easy Image X在有些PE里不能运行的解决办法
[经验] 新版SkyIAR.Easy Image X在有些PE里不能运行的解决办法 xxwl2008 发表于 2013-1-26 11:58:38 https://www.itsk.com/threa ...
- 使用ajaxfileupload插件进行Ajax Post 异步提交多个文件
前台代码: <div> <div> <img src="images/pro_upload.png" onclick="javascript ...