---------------------- <a href="http://www.itheima.com"target="blank">iOS开发</a>、<a href="http://www.itheima.com"target="blank">iOS培训</a>、期待与您交流! ----------------------
一、分类
1、作用:在不改变原来类内容的基础上,可以为类增加一些方法
2、示例代码:
// Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
NSString *_name;
}
@property NSString *name;
- (void)walk;
@end
// Person.m
#import <Foundation/Foundation.h>
#import "Person.h"
@implementation Person
- (void)walk
{
NSLog(@"Person的walk方法");
}
@end
// Person+WR.h
#import <Foundation/Foundation.h>
#import "Person.h"
@interface Person (WR)
- (void)walk;
- (void)eat;
@end
// Person+WR.m
#import <Foundation/Foundation.h>
#import "Person+WR.h"
@implementation Person (WR)
- (void)walk
{
NSLog(@"PersonWR的walk方法");
}
- (void)eat
{
NSLog(@"PersonWR的eat方法");
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Person+WR.h"
int main()
{
Person *p =[[Person alloc] init];
[p walk];
// PersonWR的walk方法
[p eat];
// PersonWR的eat方法
return 0;
}
</pre><pre>
3、使用注意
a、分类只能增加方法,不能增加成员变量(会造成成员变量的重复声明)b、分类方法实现中可以访问原来类中声明的成员变量(分类就是原来类的一部分)
c、分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没法再使用(类似继承,子类覆盖父类的方法)
d、方法调用的优先级:分类(最后参与编译的分类优先) --> 原来类 --> 父类
二、类的本质
1、类也是一个对象,是Class类型的对象,简称“类对象”,类名就代表着类对象,每个类只有一个类对象。
2、Class类型的定义
typedef struct objc_class *Class;
3、获得类对象的方式
// 第一种方式 通过类名获得
Class c = [Person class];
// 第二种方式 通过类的对象获得
Person *p = [[person alloc] init];
Class c = [p class];
4、调用类方法的方式
// 第一种方式 通过类名调用类方法
Person *p = [Person new];
// 第二种方式 通过类对象名调用类方法
Class c = [Person class];
Person *p = [c new];
5、+load和+initialize
a、+load
在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法;
先加载父类,再加载子类;也就是先调用父类的+load,再调用子类的+load;
先加载元原始类,再加载分类;
不管程序运行过程有没有用到这个类,都会调用+load加载。
b、+initialize
在第一次使用某个类时(比如创建对象等),就会调用一次+initialize方法;
一个类只会调用一次+initialize方法,先调用父类的,再调用子类的。
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
@implementation Person
+ (void)load
{
NSLog(@"Person-load");
}
+ (void)initialize
{
NSLog(@"Person-initialize");
}
@end
@interface Student : Person
@end
@implementation Student
+ (void)load
{
NSLog(@"Student-load");
}
+ (void)initialize
{
NSLog(@"Student-initialize");
}
@end
@interface Student (WR)
@end
@implementation Student (WR)
+ (void)load
{
NSLog(@"Student(WR)-load");
}
+ (void)initialize
{
NSLog(@"Student(WR)-initialize");
}
@end
int main()
{
// Person-load
// Student-load
// Student(WR)-load
Student *s = [[Student alloc] init];
// Person-initialize
// Student(WR)-initialize
return 0;
}
三、description方法
1、类中存在两个description方法,分别为类方法description和对象方法description;
2、类方法description使用NSLog(@"%@", 类名);会打印输出:类名
对象方法description使用NSLog(@"%@", 类名);会打印输出:<类名:内存地址>
四、SEL
1、SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法
a、把test2包装成SEL类型的数据
b、把test2包装成SEL类型的数据
c、根据方法地址调用对应的方法
2、示例代码
Person *p = [[Person alloc] init];
// 间接调用有参数的构造方法
[p performSelector:@selector(setName:) withObject:@"WhyRanR"]; // 注意 setName后面要加:
// 间接调用无参的构造方法
NSString *name = [p performSelector:@selector(name)];
// 获得SEL类型对象
SEL s1 = @selector(test); // 方法 -> SEL对象
SEL s2 = NSSelectorFromString(@"test"); // 方法名字符串 -> SEL对象
NSString *str = NSStringFromSelector(s); // SEL对象 -> 方法名字符串
3、得到指向当前方法的SEL对象
_cmd
---------------------- <a href="http://www.itheima.com"target="blank">iOS开发</a>、<a href="http://www.itheima.com"target="blank">iOS培训</a>、期待与您交流! ----------------------