构造方法
重写构造方法的目的:为了让对象创建出来,其成员变量就是固定值
构造方法属于对象方法
init就是构造方法,因为new方法太过于死板,只能用init来初始化,所以以后创建新对象的时候就用alloc和init的方法来实现
sample code:
int main(int argc, const char * argv[]) { Person *p = [[Person alloc] init]; // 相当于Person *p = [Person new]; p.age = 100; NSLog(@"Age is %d",p.age); return 0; }
+alloc(类方法):分配存储空间
-init(对象方法):初始化
int main(int argc, const char * argv[]) { // 要求每个Person对象被创建出来后,_age的值都是100,此时就要在.m中重写init Person *p = [[Person alloc] init]; Person *p2 = [[Person alloc] init]; NSLog(@"P Age is %d",p.age); NSLog(@"P2 Age is %d",p2.age); return 0; } -------------------------------------------.m文件中进行init的重写------------------------------------------- @implementation Person - (id)init { self = [super init];// 一定要调用回super的init方法:初始化父类中声明的一些成员变量和其他属性,其实就是调用其父类中的init方法 if (self != nil) { // 如果不是空,说明才有初始化的必要 _age = 100; // 初始化_age的值 } return self; // 返回初始化好的值 } @end
精简后的代码
- (id)init
{
if (self = [super init]) { // 如果不是空,说明才有初始化的必要
_age = 100; // 初始化_age的值
}
return self; // 返回初始化好的值
}
1.先调用父类的构造方法(NSOject-->父类-->子类)(super init)
2.再进行子类内部成员变量的初始化
自定义构造方法的意义:将成员变量初始化
自定义构造方法的命名规范:
1.一定是对象方法,一定以减号开头
2.返回值一般是id类型
3.方法名一般以initWith开头
其定义方法和init的重新构造差不多
首先,先在.h文件中进行自定义构造方法的声明;然后再在.m文件中进行实现
例如:
.h文件:
- (id)initWithName:(NSString *)name;
.m文件:
- (id)initWithName:(NSString *)name { if (self = [super init]) { _name = name; } return self; }
main函数中调用:
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { Person *p = [[Person alloc] initWithName:@"Rose"]; NSLog(@"%@",p.name); return 0; }
1.在子类里自定义构造方法时,如果自定义的构造方法中的变量子类没有声明,而存在于父类中,此时就要用set方法或点语法来给变量初始化值.
例如:
@implementation Student // name,age变量是Student的父类Person类中,所以重新初始化的时候要用点语法,因为父类中的变量属于@private的 - (id)initWithNo:(int)no andName:(NSString *)name andAge:(int)age { if ( self = [super init]) { _no = no; self.name = name; self.age = age; } return self; } @end
2.但其实在子类实现中用点语法或set方法初始化父类中的变量在实际写代码中不常用
可以在返回父类的init方法,然后子类再重新定义并初始化自己的变量
例如:
@implementation Student - (id)initWithNo:(int)no andName:(NSString *)name andAge:(int)age { // 这样直接返回到父类的构造方法中,父类把自己的变量初始化 if (self = [super initWithName:name andAge:age]) { _no = no; } return self; } @end
这样写的好处是:
1>每个方法分工分明,父类方法在父类初始化,子类在子类初始化
2>如果父类中有代码改动,子类无需更改
大致思想就是,父类的属性交给父类去处理,子类的交给子类来处理
分类的意思在于不修改原代码的前提下给某一个类扩充一些方法
格式:
// 声明 @interface 类名(分类名称) // 一般分类名称默认用模块名 @end // 实现 @implementation 类名(分类名称) @end
1.如果一个类非常庞大, 需要很多种方法来实现,这个时候就可以把这些方法分类来写,每个方法写成一个类.这样就 可以把这些类分给不同的人来写,这样节省工作时间,例如团队开发中经常用到。
2.因为每个类都是单独的,所以管理和修改起来也很方便
1.不能扩充成员变量,只能添加方法
2.分类方法中可以访问原来类中的成员变量
3.如果重新定义分类中的方法,会把原方法覆盖掉
4.方法调用优先级:分类-->原类-->父类
5.如果两个分类中都有相同的方法,将会调用最后编译的那个分类中的方法
6.分类可以定义在单独的.h和.m文件中,也可以定义在当前类中,一般情况下都是定义在单独的文件中
.h文件
#import <Foundation/Foundation.h> @interface NSString (Calculate_Number) + (int) Calculate_NumberInString:(NSString *)str; @end
.m文件
#import "NSString+Calculate_Number.h" @implementation NSString (Calculate_Number) + (int)Calculate_NumberInString:(NSString *)str { int count = 0; for (int i = 0; i < str.length; i++) { unichar c = [str characterAtIndex:i]; if (c >= '0' && c <= '9') { count++; } } return count; } @end
添加对象方法:
.h文件
#import <Foundation/Foundation.h> @interface NSString (Calculate_Number) - (int) Calculate_Number; @end
.m文件
- (int)Calculate_Number { int count= 0; for (int i = 0; i < self.length; i++) { unichar ch = [self characterAtIndex:i]; if (ch >='0' && ch <='9') { count++; } } return count; }
其实可以在类方法中调用对象方法
+ (int)Calculate_NumberInString:(NSString *)str { return [str Calculate_Number]; }
load方法:
在类被加载的时候,调用load方法
先加载父类的,再加载子类的
程序一启动,每个类里都要调用一遍
initialize方法:
当第一次用到这个类的时候,才会调用,也是先父类,后子类
如果有分类,优先分类