郝萌主倾心贡献。尊重作者的劳动成果,请勿转载。

假设文章对您有所帮助。欢迎给作者捐赠,支持郝萌主。捐赠数额任意,重在心意^_^

我要捐赠: 点击捐赠

Cocos2d-X源代码下载:点我传送

分类与协议是OC比較有特色的部分。

从表面来看,
分类呢有点类似抽象方法在抽象类中(C++或者Java里的那个抽象类概念)。

协议类似接口(Java语言那个接口),可是又不能“一视同仁”。

分类概念
分类(Category) 同意向一个类文件里加入新的方法声明, 
它不须要使用子类机制, 而且在类实现的文件里的同一个名字下定义这些方法。 
其语法举比例如以下: 
#import
"ClassName.h"

@interface ClassName ( CategoryName )

// 方法声明

@end
分类实例



上一篇多态性介绍中以前使用过Vector和Scalar的样例, 
以下我们为Vector添加“减”sub的方法。

Vector+sub.h文件
#import <Foundation/Foundation.h>
#import "Vector.h" @interface Vector (sub) -(Vector *) sub: (Vector *) v; @end
Vector+sub.m文件
#import "Vector+sub.h"

@implementation  Vector (sub) 

-(Vector *) sub: (Vector *) v {
Vector *result = [[Vector alloc] init];
[result setVec1: vec1 - [v vec1] andVec2: vec2 - [v vec2]];
return result;
} @end
调用的main函数
#import <Foundation/Foundation.h>
#import "Vector+sub.h" int main (int argc, const char * argv[]) { Vector *vecA =[[Vector alloc] init];
Vector *vecB =[[Vector alloc] init];
id result; //set the values
[vecA setVec1: 3.2 andVec2: 4.7];
[vecB setVec1: 32.2 andVec2: 47.7]; // print it
[vecA print];
NSLog(@" + ");
[vecB print];
NSLog(@" = ");
result = [vecA add: vecB];
[result print]; [vecA print];
NSLog(@" - ");
[vecB print];
NSLog(@" = ");
result = [vecA sub: vecB];
[result print]; // free memory
[vecA release];
[vecB release];
[result release];
return 0;
}
当中result = [vecA add: vecB] 中的add: 是Vector类原有的方法。 
result = [vecA sub: vecB] 中的sub: 是Vector分类加入的方法。



分类是在Java和C++等面向对象的语言中没有的概念, 
分类本质上是通过Objective-C的动态绑定而实现的。

通过分类使用可以达到比继承更好的效果。

从上面这个样例能够看到,分类提供了一种简单的方式。

用它能够将类的定义模块化到相关方法的组或分类中。

它还提供了扩展现有类定义的简便方式,而且不必訪问类的源码,也不须要创建子类。

#import "Fraction.h"

@interface Fraction (MathOps)

-(Fraction *) add: (Fraction *) f;

-(Fraction *) mul: (Fraction *) f;

-(Fraction *) sub: (Fraction *) f;

-(Fraction *) div: (Fraction *) f;

@end

注意,这既是接口部分的定义,也是现有接口部分的扩展。

因此。必须包含原接口部分,这样编译器就知道Fraction类。

依照惯例。作为分类的.h和.m文件的基本名称是由类的名称紧接着分类的名称。

比如:FractionMathOps.m;

一些程序猿使用符号“+”来分隔类和分类的名称,比方Fraction+MathOps.h。

只是不建议这样命名。

类的扩展:

创建一个未命名的分类。且在括号“()”之间不指定名字,这是一种特殊的情况。

这样的特殊的语法定义为类的扩展。

未命名类中声明的方法须要在主实现区域实现,而不是在分离的实现区域中实现。

未命名分类是很实用的,由于它们的方法都是私有的。

假设须要写一个类,并且数据和方法仅供这个类本身使用,未命名类比較合适。

关于分类的注意事项:

分类能够覆写该类中的还有一个方法,可是通常觉得这样的做法是做虐的设计习惯。所以须要注意:

第一、覆写了一个方法后。再也不能訪问原来的方法。(假设确实须要覆写方法。正确的选择可能是创建子类。)

第二、通过使用分类加入新的方法来扩展类不只影响这个类,同一时候也会影响它的全部子类。

第三、对象/分类命名对必须是唯一的。

由于大家使用的名称空间是程序代码、库、框架和插件共享的。


协议(Protocol ) 
与Java的Interface(接口 )或者C++的纯虚类同样,就是用来声明接口的。
协议仅仅是定义了方法的列表,协议不负责实现方法。目的是让别的类来实现。

以Graphics协议为例:
Graphics中定义了onDraw方法, 可是我们细致分析一下onDraw方法不能实现的。 
作为Graphics(几何图形)它无法知道它的子类怎样绘制图形。 
它仅仅能规定绘制图名字为onDraw签名和返回值等信息, 但不能给出详细的实现, 
因此Graphics(几何图形) 不应该设计成为类而应该设计成为协议。 



@protocol Graphics

-(void) onDraw;

@end

协议仅仅有接口部分, 没有实现部分, 所以没有m文件, keyword@protocol , 
协议能够继承别的协议, 协议中不能定义成员变量。

协议实现类Ellipse
#import <Foundation/Foundation.h>
#import "Graphics.h" @interface Ellipse:NSObject <Graphics> { } @end
#import "Ellipse.h"

@implementation Ellipse

-(void)onDraw {
NSLog(@"绘制椭圆形");
} @end
协议实现类Triangle
#import <Foundation/Foundation.h>
#import "Graphics.h" @interface Triangle:NSObject <Graphics> { } @end
#import "Triangle.h"

@implementation Triangle

-(void)onDraw {
NSLog(@"绘制三角形");
} @end
代码说明:
协议的实现是在类声明的父类之后, 加上<Graphics>,
与类的单个继承不同, 
协议能够实现多个, 表示要实现这个协议, 
假设有多个协议要实现用“,” 号分隔: <P1,P2>。

调用的main函数
#import <Foundation/Foundation.h>
#import "Graphics.h"
#import "Ellipse.h"
#import "Triangle.h" int main (int argc, const char * argv[]) { id graphics;
graphics = [[Ellipse alloc] init];
[graphics onDraw];
[graphics release]; graphics = [[Triangle alloc] init];
[graphics onDraw];
[graphics release]; return 0;
}

从上面的样例能够看出:

协议是多个类共享的一个方法列表。

协议中列出的方法没有对应的实现,计划由其它人来实现。

协议提供了一种方式。用指定的名称定义一组多少有点相关的方法。

假设决定实现特定协议的全部方法,也就意味着要遵守(confirm to)或採用(adopt)这项协议。

定义一个协议非常easy:仅仅要使用@protocol指令。然后跟上你给出的协议名称。

比如:

@protocol NSCoping

- (id) copyWithZone: (NSZone *) zone;

@end

这里再提到两个重要的协议:

NSCopying

NSCoding

假设你的类採用NSCopying协议,则必须实现copyWithZone:的方法

通过在@interface行的一对尖括号(<....>)内列出协议名称。能够告知编译器你正在採用的一个协议。

这项协议的名称放在类名和它的父类名称之后,

比如:

@interface AddressBook:NSObject <NSCoping>

假设你的类採用多项协议,仅仅需把它们都列在尖括号里,并用逗号分开。比如:

@interface AddressBook:NSObject <NSCoping, NSCoding>

假设你定义了自己的协议,那么不必由自己实现它。

假设一个类遵守NSCoping协议。则它的子类也遵守NSCoping协议

(只是并不意味着对该子类而言。这些方法得到了正确的实现)。

@required和@optionalkeyword


@protocol MyProtocol

- (void) requiredMethod;

@optional

- (void) anOptionalMethod;

- (void) anotherOptionalMethod;

@required

- (void) anotherRequiredMethod;

@end

注意。这里使用了@optional指令。

该指令之后列出的全部方法都是可选的。

@required指令之后的是须要的方法。


注意,协议不引用不论什么类,它是无类的(classless)。

不论什么类都能够遵循MyProtocol协议。

能够使用conformsToProtocol:方法检查一个对象是否遵循某些协议。

比如:

if ([currentObject conformsToProtocol: @protocol (MyProtocol)] == YES) {

...

}

这里使用的专用@protocol指令用于获取一个协议名称,并产生一个Protocol对象。

conformsToProtocol:方法期望这个对象作为它的參数。

通过在类型名称之后的尖括号里加入协议名称。能够借助编译器来检查变量的一致性。

比如:

id <Drawing> currentObject;

这告知编译器currentObject将包括遵守Drawing协议的对象。

假设这个变量保存的对象遵守多项协议,则能够列出多项协议 ,

例如以下面代码:

id <NSCoping, NSCoding> myDocument;

定义一项协议时。能够扩展现有协议的定义。

如:

@protocol Drawing3D <Drawing> Drawing3D 协议也採用了Drawing协议。

最后要说的是。分类也是能够採用一项协议。

和类名一样,协议名必须是唯一的。

代理:

协议也是一种两个类之间的接口定义。

定义了协议的类能够看做是将协议定义的方法代理给了实现它们的类。

非正式(informal)协议:是一个分类,列出了一组方法但并没有实现它们。

因此,非正式分类一般是为根类定义的。有时,非正式协议也称为抽象(abstract)协议。

非正式协议实际上仅仅是一个名称下的一组方法。

声明非正式协议的类自己并不实现这些方法。

而且选择实现这些方法中的子类须要在它的接口部分又一次声明这些方法。

同一时候还要实现这些方法中的一个或多个。

注意:前面描写叙述的@optional指令加入到了Objective-C 2.0语言中,用于代替非正式协议的使用。

合成对象:

能够定义一个类包括其它类的一个或多个对象。

这个新类的对象就是所谓的合成(composite)对象,由于它是由其它对象组成的。

子类依赖于父类。改变了父类有可能会使得子类中的方方法不起作用。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Objective-C马路成魔【12-分类和协议】的更多相关文章

  1. Objective-C马路成魔【14-关键C语言功能】

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 这里介绍一 ...

  2. 成魔笔记1——先入IT,再成魔

    关于我为什么要写这个博客的原因,做一个简单的解释.因为报考的一时兴起,我选择了软件专业.可是三年下来,感觉自己没做多少事,也没收获到多少东西.很多时候都是老师讲什么,都是完全陌生的东西,跟不上教学的思 ...

  3. Objective-C之成魔之路【0-序章】

    郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助.欢迎给作者捐赠,支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 C语言首创 ...

  4. 第12讲 | TCP协议(下):西行必定多妖孽,恒心智慧消磨难

    第12讲 | TCP协议(下):西行必定多妖孽,恒心智慧消磨难 如何做个靠谱的人? 有问有答,任务发送和接收有记录,完成有反馈. 如何实现一个靠谱的协议? TCP 协议使用的也是同样的模式.为了保证顺 ...

  5. 机器学习入门12 - 分类 (Classification)

    原文链接:https://developers.google.com/machine-learning/crash-course/classification/ 1- 指定阈值 为了将逻辑回归值映射到 ...

  6. Objective-C之成魔之路【5-选择结构】

    郝萌主倾心贡献.尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 Objec ...

  7. Objective-C之成魔之路【16-使用文件】

    郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠.支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 语言的设计 ...

  8. Objective-C之成魔之路【9-类构造方法和成员变量作用域、以及变量】

    郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 构造方法 ...

  9. 将decimal类型的数据转成2.12这样价钱的显示方式

    UnitPrice = string.Format("{0:.00}", m.UnitPrice),

随机推荐

  1. 简单的dialog菜单

    本文介绍的是我自己做的一个简单的dialog菜单,可以直接植入到类中. 方法代码: /** 显示一个靠右上的dialog列表菜单*/private void showTopBarRightButton ...

  2. java nio 网络框架实现(转)

    maven项目https://github.com/solq360/common 链式编/解码 链路层链式处理 管道管理socket 多协议处理非常方便 仿netty NioEventLoop 单线程 ...

  3. 什么时候PHP经验MySQL存储过程

    1.MySQL存储过程 数据库语言,我们经常使用的操作SQL语句必须首先编译在运行时.然后运行,存储过程(Stored Procedure)它被设置为完成一个特定的功能SQL报表设置.编译存储在数据库 ...

  4. Android ListView分页载入(服务端+android端)Demo

    Android ListView分页载入功能 在实际开发中经经常使用到,是每一个开发人员必须掌握的内容,本Demo给出了服务端+Android端的两者的代码,并成功通过了測试. 服务端使用MyEcli ...

  5. vs2015基于VisualStudioOnline协同工作流程

    项目负责人登陆自己的vsonline新建项目就不多说了. 直接从邀请队友开始 项目负责人操作 被邀请的邮箱务必是可以登录visualstudio的邮箱 发送邀请后,被邀请人登陆自己的邮箱,查看邀请人发 ...

  6. iOS_38_手势

    Pan平移手势 终于效果图: Swipe轻扫手势 LongPress长按手势 Pinch和Rotation手势 捏合(缩放)和旋转 终于效果图: 涂鸦 终于效果图: 事件分3大类:触摸.加速计.远程遥 ...

  7. Objective-c正确的写法单身

    Singleton模式iOS发展可能是其中最常用的模式中使用的.但是因为oc语言特性本身,想要写一个正确的Singleton模式是比较繁琐,iOS中单例模式的设计思路. 关于单例模式很多其它的介绍请參 ...

  8. 基于AVR128单纯Modbus协议实施

    Modbus通信协议Modicon公司1979在发展中,适用于工业现场总线协议控制.Modbus通信系统包含芯片的节点,并与组合物可编程控制的公共传输线,它的目的是收集和监视多个节点的数据.Modbu ...

  9. Delete和Truncate的区别

    原文:Delete和Truncate的区别 一般对于没有用的数据,都会经行删除,而删除通常使用的是DELETE和TRUNCATE命令.对于有条件地删除,基本上就会使用DELETE,当然还是没有绝对,用 ...

  10. 推荐几个我一直在使用chrome小工具(上)

    我用的chrome插件挺多的,所谓工欲善其事必先利其器,我热衷于搜寻好用的工具来让我平时的工作事半功倍. 以下介绍几款我正在用的感觉还不错的插件,假设大家还有其他好用的(肯定有,chrome插件库太庞 ...