ObjC第五节:协议和分类
2015-08-18 09:41
330 查看
协议和分类
1、协议
2、NSCoping
3、分类
4、其他特性
5、扩展
1、协议、分类、继承
MyPoint.h(主类)
Computer.h
PC.h
main.m
1、协议
2、NSCoping
3、分类
4、其他特性
5、扩展
1、协议、分类、继承
MyPoint.h(主类)
#import <Foundation/Foundation.h> @interface MyPoint : NSObject <NSCopying> //相当于重复遵守copy协议 { int x, y; } @property (nonatomic) int x, y; - (void) print; - (void) over; @endMyPoint.m
#import "MyPoint.h" @implementation MyPoint //如果没有实现required协议,会警告 #warning 没有实现方法 //这个就是标记此处代码有一个警告,Xcode会在此处显示黄色标记,这个作用就是给自己添加一个标记,后续在来查看 @synthesize x, y; - (void) print { NSLog(@"X= %d, Y= %d", x, y); } - (void) over //将要被重写的方法,不建议分类重写,因为会覆盖原方法致原方法不可用 { NSLog(@"+++"); } @endABdraw.h(协议)
#import <Foundation/Foundation.h> @protocol ABdraw <NSObject> //协议同样可以遵守其他协议 - (void) AB; //默认@required @required - (void) draw; @optional - (id) copyWithZone:(NSZone *) zone; //这里声明了一个与NSCoping一样的方法,但它是选择实现的,凡出现@optional修饰的协议均为非正式协议 @endMyPoint+Pointe2.h(分类)
#import "MyPoint.h" #import "ABdraw.h" @interface MyPoint (Point2) <ABdraw> //分类遵守的协议,相当于整个类都遵守 //- (void) draw; //协议,不需声明 - (void) over; @endMyPoint+Pointe2.m
#import "MyPoint+Point2.h" @implementation MyPoint (Point2) - (void) over { NSLog(@"222"); } #pragma mark - ABdraw //这个作用就是做一下标记,标记后面的方法都是协议中的方法,这样就可以将一个类中的方法类别分的更细,我们在文件导航栏中进行查看 - (void) draw; { NSLog(@"X~~%d, y~~%d", x * x, y * y); } - (void) AB //可以看到,只要实现协议方法就不会警告,即使该实现为空 { } - (id) copyWithZone:(NSZone *) zone { MyPoint * newPoint = [[MyPoint allocWithZone:zone] init]; newPoint.x = x; newPoint.y = y; return newPoint; } @endNewPoint.h(分类)
#import <Foundation/Foundation.h> #import "MyPoint.h" @interface MyPoint (Rel) //分类,建议命名按照“主类+分类” - (void) moveTo:(int)_x :(int)_y; - (void) over; @endNewPoint.m
#import "NewPoint.h" @implementation MyPoint (Rel) -(void) moveTo:(int)_x :(int)_y { x = _x; y = _y; } - (void) over { NSLog(@"NNN"); } @endCircle.h(子类)
#import <Foundation/Foundation.h> #import "MyPoint.h" @interface Circle : MyPoint //子类,继承主类,分类的方法同样被继承 @property (nonatomic) int radius; - (void) print; - (void) over; @endCircle.m
#import "Circle.h" @implementation Circle @synthesize radius; - (void) print { [super print]; NSLog(@"Circle at (%d, %d) with %d", x, y, radius); } - (void) over //实验,同样重写该方法,可以看到,子类可以调用到正确版本 { NSLog(@"CCC"); } @endmain.m
//(1)当程序启动时,就会加载项目中所有的类。并且在类被加载完毕后会调用+ (void)load类方法,先加载父类load ,后加载子类的load方法,最后分类 //(2)在类首次使用时,会调用一次+initialize方法,先加载父类initialize ,后加载子类的initialize 方法 //(3)在使用分类时,分类的load方法也会被加载,而且对于initialize方法,会调用子类的initialize的方法。 这里其实还是那个分类的基本原理,调用类和分类的同名函数时是会加载分类的方法 //(4)注意:在初始化的时候,如果在分类中重写了+initialize方法,则会覆盖掉父类的。 //(5)重写+initialize方法可以监听类的使用情况。 #import <Foundation/Foundation.h> #import "Circle.h" //#import "NewPoint.h" //如果不包含,会警告实例方法moveTo没找到(返回类型默认id),但正常运行,建议包含分类头文件 #import "MyPoint+Point2.h" #import "NewPoint.h" int main() { MyPoint * p = [[MyPoint alloc] init]; p.x = 1; p.y = 1; [p print]; [p moveTo:3 :3]; //分类方法 [p print]; [p draw]; //分类方法 [p over]; //分类重写的方法,调用分类中最后编译的那个方法(也有一种说法,编译器不知道调用哪一种方法) if ([p respondsToSelector:@selector(copyWithZone:)]) { //respondsToSelector:@selector(方法名),这个方法的作用是判断当前对象中是否定义了一个方法,一般情况下,当协议中有@optional修饰的方法且需要调用该方法时,都需要先判断再调用 MyPoint * p2 = [p copy]; //copy,协议 [p2 print]; [p2 release]; } Circle * c = [[Circle alloc] init]; c.x = 2; c.y = 2; c.radius = 5; [c print]; [c draw]; //分类方法 [c over]; //子类重写的方法,调用子类方法 [p release]; [c release]; return 0; }2、子类copy
Computer.h
#import <Foundation/Foundation.h> @interface Computer : NSObject <NSCopying> @property (nonatomic) int height, width; - (id) initWithHeight:(int)_height Width:(int)width; - (void)print; @endComputer.m
</pre><pre name="code" class="objc">#import "Computer.h" @implementation Computer @synthesize height, width; - (id) initWithHeight:(int)_height Width:(int)_width { if (self = [super init]) { height = _height; width = _width; } return self; } - (void)print { NSLog(@"Height: %d, Width: %d", height, width); } #pragma mark --Copy - (id)copyWithZone:(NSZone *)zone { Computer * c = [[[self class] allocWithZone:zone] init]; //注意[self class],获取调用该方法的对象所在的类,为子类调用父类的copy而能够创建正确空间做基础 c.height = height; c.width = width; return c; } @end
PC.h
#import <Foundation/Foundation.h> #import "Computer.h" @interface PC : Computer @property (nonatomic) int num, color; - (id) initWithHeight:(int)_height Width:(int)_width Num:(int)_num Color:(int)_color; - (void)print; @endPC.m
<pre name="code" class="objc">#import "PC.h" @implementation PC @synthesize num, color; - (id) initWithHeight:(int)_height Width:(int)_width Num:(int)_num Color:(int)_color { if (self = [super initWithHeight:_height Width:_width]) { num = _num; color = _color; } return self; } - (void)print { [super print]; NSLog(@"Num: %d, Color: %d", num, color); } - (id)copyWithZone:(NSZone *)zone { //PC * p = [[PC allocWithZone:zone] initWithHeight:self.height Width:self.width Num:num Color:color]; //1、使用初始化函数,在这里用实例变量进行赋值,此时可以一次性把子类的所有实例变量赋值(父类和子类) //p.height = self.height; //2、使用@property的set函数一一赋值 //p.width = self.width; //[super copy]; //相当于创建了一个临时的父类对象,不可 PC * p = [super copyWithZone:zone]; //此时因为p1调用copy,self就是p1,(super告诉编译器到self的父类),父类调用copyWithZone:方法,而父类中,[self class]使创建空间的类是子类,而不是父类,就成功创建子类(p2)的空间,(此时父类c是子类p2中父类的部分)接着把p1中父类的部分赋值给p2,然后回到子类方法,继续把p1子类自己的部分赋值给p2 p.num = num; p.color = color; //p = [super initWithHeight:self.height Width:self.width]; //赋值正确运行崩溃 - -,不可 return p; } @end
main.m
#import <Foundation/Foundation.h> #import "PC.h" int main () { Computer * c1 = [[Computer alloc] init]; c1.height = 1; c1.width = 2; [c1 print]; Computer * c2 = [c1 copy]; [c2 print]; PC * p1 = [[PC alloc] init]; p1.num = 1001; p1.color = 1002; p1.height = 101; p1.width = 102; [p1 print]; PC * p2 = [p1 copy]; [p2 print]; [c1 release]; [c2 release]; [p1 release]; [p2 release]; return 0; }3、代理(委托)见下节
相关文章推荐
- ObjC第一节:OC类、消息
- ObjC第二节:属性声明、类的组合
- ObjC第三节:内存管理
- ObjC第四节:继承
- ObjC第七节:文件操作
- ObjC第六节:(2)OC常用类
- ObjC第六节:OC常用类
- ObjC第五节:(2)代理(委托)
- 生成表insert into语句的存储过程
- 一种高效无锁内存队列的实现
- unsigned int 与 字符串 之间相互转换
- Rpc 详解
- POJ 2155 Matrix
- WinForm点击按钮在对应的panel里画图
- CSS中属性position位置详解功能讲解与实例分析
- 阿里校招在线笔试
- cocos2dx ——屏幕适配
- Linux下MySQL的彻底卸载和安装配置字符集 .
- poj 1985 Cow Marathon【树的直径裸题】
- android中保存一个ArrayList到SharedPreferences的方法