这篇文章记录一下OC语法里面的构造方法、分类以及类的一些研究
1.构造方法
一般我们创建一个对象是写成 Person * p = [Person new]; 其实在内存中是分两个方法来实现的,[[Person alloc] init]; alloc方法是先分配一个有存储空间的对象给用户,然后init方法给对象初始化,int方法即构造方法;而系统初始化对象的值一般都是0,为了让对象创建出来时,成员变量就有一定的值,所以可以重写构造方法来让新创建出来的对象成员变量具有一定的值。
#import<Foundation/Foundation.h>
@interface Person:NSObject
@property int age;
@end
@implementation Person
// 重写 -init方法(构造方法)
- (id)init
{
// 1.一定要调用父类的init方法:初始化父类中声明的一些成员变量
self = [super init]; // 当前对象
if(self ! = nil)
{ // 2.初始化成功,才有必要进行接下来的当前对象的成员变量的初始化,创建出来的新的对象age初始值全为10,
_age = 10;
}
// 3.返回一个已经初始化完毕的对象
return self;
}
/* if(self = [super init])
{
_age = 10;
}
return self;*/
@end
注意点:既然init是给对象成员变量初始化用的,所以init为对象方法,不是类方法;alloc是类方法,某个类调用该方法分配一个该类型的对象:
Person *p = [Person new];
拆分: 完整地创建一个可用的对象
1.调用+alloc分配存储空间
Person *p1 = [Person alloc];
2.调用-init进行初始化
Person *p2 = [p1 init];
即Person *p = [[Person alloc] init];
2.自定义构造方法
自定义构造方法一般是:想给需要初始化的对象的某个成员变量传入一个特定的值;自定义的构造方法一定是对象方法,返回值一般是id类型,方法名一般以initWith开头
#import<Foundation/Foundation.h>
@interface Person:NSObject
@property NSString *name;
@property int age;
- (id)initWithName:(NSString *)name;
- (id)initWithName:(NSString *)name andAge:(int)age; // 自定义了两个构造方法,一个是传名字的,一个是传名字跟年龄的
@end
@implementation Person
- (id)initWithName:(NSString *)name
{
if(self = [super init])
{
_name = name;
}
return self;
}
- (id)initWithName:(NSString *)name andAge:(int)age // 实现方法
{if(self = [super init])
{
_name = name; _age = age;}
return self;
}
@end
@interface Student:Person // 继承了Person类
@property int no;
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no; // 自己定义了一个构造方法
@end
@implementation Student
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{ // 调用父类自定义的构造方法,将父类中有的成员变量先初始化,再初始化自己特有的成员变量 </span>
if(self = [super initWithName:name andAge:age])
{ _no = no;}
return self;
}
@end
int main()
{
Person *p = [[Person alloc] initWithName:@"jim" andAge:1];
Student *p1 = [[Student alloc] initWithName:@"jim" andAge:1 andNo:12];
return 0;
}
3.分类
分类可以给一个类扩充一些方法(不修改原来类的代码);而且可以新建一个分类文件,有利于团队开发,一个功能里面的所有方法可以归为一类,分模块开发,分类的声明跟实现格式如下:@interface 类名(分类名称)@end
@implementation 类名(分类名称)@end分类的使用注意:
1.分类只能增加方法,不能增加成员变量,
2.分类方法实现中可以访问原来类中声明的成员变量
3.分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,导致原来的方法没办法再使用(因为同名的方法,优先去分类中查找,然后再去原来类中查找,最后再去父类中查找)
如果一个类的好几个分类中有同一个方法,优先调用最后编译的分类文件方法。
以下代码是给系统自带的NSString类新增分类:
#import <Foundation/Foundation.h>
@interface NSString (number)
+ (int)numberCountOfString:(NSString *)str; // 类方法
- (int)numberCount; // 对象方法
@end
@implementation NSString (number)
+ (int)numberCountOfString:(NSString *)str // 计算传入的字符串的数字的个数
{
return [str numberCount];
}
- (int)numberCount // <span style="font-family: Arial, Helvetica, sans-serif;">计算调用对象的字符串的数字个数</span>
{
int count = 0;
for(int i=0;i<self.length;i++)
{
unichar c = [self characterAtIndex:i];
if(c >= '0' && c =< '9')
count++;
}
return count;
}
@end
int main()
{
int count = [NSString numberCountOfString:@"232121adafafd"];
NSLog(@"%d",count);
int count1 = [@"121214ddfdf" numberCount];
NSLog(@"%d",count1);
return 0;
}
4.类
类本身也是一个对象,是Class类型的对象,(Class =(Class *)),简称类对象。利用Class创建 Person类对象,再利用Person类对象创建Person类型的对象,同一个类型的对象只有一个类对象。
类的加载:先加载父类,再加载子类,先加载原始类,再加载分类
类的初始化时 先初始化父类 再初始化子类,当只初始化父类的时候,优先使用分类里面的方法
#import <Foundation/Foundation.h>
@interface Person:NSObject
+ (void)test;
@end
@implementation Person
+ (void)test
{
NSLog(@"调用了test类方法");
}
// 当程序启动的时候,就会加载一次项目中所有的类和分类,类加载完毕后就会调用所有类和分类的+load方法,只调用一次
+ (void)load
{
NSLog(@"Person--load");
}
// 当第一次使用这个类的时候,就会调用当前类的+initialize方法,一个类只会调用一次+initialize方法,先调用父类,再调用子类
+ (void)initialize
{
NSLog(@"Person--initialize");
}
@end
@interface Student:Person
@end
@implementation Student
+ (void)load
{
NSLog(@"Student--load");
}
+ (void)initialize
{
NSLog(@"Student--initialize");
}
@end