OC第三篇—id类型和构造方法
一、id类型:
1. 本质:id类型是指针。
2.作用:万能指针,能指向任何OC对象,相当于NSObject *.
3. 使用示例:
id p = [Person new];
代码示例:
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Person *p = [Person new];
//[p fsdfdsfd];
NSObject *o = [Person new];
// id == NSObject *
// 万能指针,能指向\操作任何OC对象
id d = [Person new];
[d setAge:10];
[d setObj:@"321423432"];
NSLog(@"%d", [d age]);
}
return ;
}
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@property id obj;
@end
#import "Person.h"
@implementation Person
@end
代码分析:id类型可以指向Peson这个类型,并且操作Person的方法,和用Object的作用类似。
二、构造方法:
1. 本质:方法的重写。
2. 作用:用于初始化对象方法
3. 创建对象的原理:
1).分配存储空间 [类名 alloc]; 调用类方法返回未初始化的对象 +alloc
2). 初始化对象 [对象名 init]; 调用对象方法进行初始化返回对象本身 -init
示例:
Person *p1 = [Person alloc];
Person *p1 = [p1 init];
合成一句后:
Person *p = [[Person alloc] init];
4.方法的重写:
init是初始化,方法的重写就是重写inti方法。
示例:
- (id)init
{
if (self = [super init]) //初始化成功,才有必要再进行初始化
{
_age = 10;
}
return self;
}
5. super调用:
必要要先调用super方法,用来初始化父类中的成员变量。Object中有isa指针,因此一定要先调用super的init方法。
代码示例:
Person类:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@end
#import "Person.h"
@implementation Person
// 重写-init方法
//- (id)init
//{
// // 1.一定要调用回super的init方法:初始化父类中声明的一些成员变量和其他属性
// self = [super init]; // 当前对象 self
//
//
// // 2.如果对象初始化成功,才有必要进行接下来的初始化
// if (self != nil)
// { // 初始化成功
// _age = 10;
// }
//
// // 3.返回一个已经初始化完毕的对象
// return self;
//}
- (id)init
{
if ( self = [super init] )
{ // 初始化成功
_age = 10;
}
// 3.返回一个已经初始化完毕的对象
return self;
}
@end
Student类:
#import "Person.h"
@interface Student : Person
@property int no;
@end
#import "Student.h"
@implementation Student
// 学生对象初始化完毕后,年龄就是10,学号就是1
- (id)init
{
if ( self = [super init] )
{
_no = 1;
}
return self;
}
@end
main函数:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
// 构造方法:用来初始化对象的方法,是个对象方法,-开头
// 重写构造方法的目的:为了让对象创建出来,成员变量就会有一些固定的值
/*
重写构造方法的注意点
1.先调用父类的构造方法([super init])
2.再进行子类内部成员变量的初始化
*/
int main()
{
// Person *p = [Person new];
/*
完整地创建一个可用的对象
1.分配存储空间 +alloc
2.初始化 -init
*/
// 1.调用+alloc分配存储空间
// Person *p1 = [Person alloc];
// 2.调用-init进行初始化
// Person *p2 = [p1 init];
// // 调用-init进行初始化
// Person *p3 = [Person new];
//
//
// // 每个Person对象创建出来,他的_age都是10
//
Person *p4 = [[Person alloc] init];
Student *stu = [[Student alloc] init];
NSLog(@"------");
return 0;
}
6.自定义构造方法:
1).方法名都以init开头
2).返回值是id类型
代码示例:
- (id)initWithAge:(int)age {
if (self = [super init]) {
_age = age;
}
return self;
}
三、Category使用:
1. 作用:在不改变原来类的基础上,可以为类增加一些方法。
2.分类的使用格式:
分类的声明
@interface 类名 (分类名称)
// 方法声明
@end
分类的实现
@implementation 类名 (分类名称)
// 方法实现
@end
代码示例:
Person 类:
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
int _age;
}
@property int age;
- (void)test;
@end
#import "Person.h"
@implementation Person
// 只有一个test方法
- (void)test
{
NSLog(@"Person-test");
}
@end
Person+JJ 分类:
#import "Person.h"
@interface Person (JJ)
- (void)test2;
@end
#import "Person+JJ.h"
@implementation Person (JJ)
// 增加了一个test2方法
- (void)test2
{
NSLog(@"-----test2");
}
// 如果在分类中定义一个和原类相同的方法,则执行分类的方法,原类不执行
- (void)test
{
NSLog(@"Person (JJ)-test");
}
@end
Person+MJ 分类:
#import "Person.h"
@interface Person (MJ)
- (void)study;
@end
#import "Person+MJ.h"
@implementation Person (MJ)
- (void)study
{
NSLog(@"学习-----%d", _age);
}
- (void)test
{
NSLog(@"Person (MJ)-test");
}
@end
main 函数:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Person+JJ.h"
#import “Person+MJ.h”
int main()
{
Person *p = [[Person alloc] init];
//p.age = 10;
// 优先去分类中查找,然后再去原来类中找,最后再去父类中找
[p test];
// [p study];
return 0;
}
3.Category使用注意:
1). Category可以访问原始类的实例变量,但不能添加变量,只能添加方法。如果想添加变量,可以考虑通过继承创建子类
2). Category可以实现原始类的方法,但不推荐这么做,因为它是直接替换掉原来的方法,这么做的后果是再也不能访问原来的方法
3). Category实现中可以访问原来类中的成员变量
4).方法调用优先级:分类(最后参与编译的分类) ->原来类 ->父类
4.Category的好处:
1). 一个庞大的类可以分模块开发
2). 一个庞大的类可以由多个人来编写,更有利于团队合作