在Objective-C语言中, 类别、类扩展(也称为匿名类别)以及协议是Objective-C 语言级别支持的模式,用来实现对类进行功能扩展。

一、类别--用来增加方法到已存在类

声明一个类别的语法如下:

@interface ClassName (CategoryName)

@end

Objective-C 的标准的类声明,也使用@interface 关键字。但类别与类声明区别的是在括号中声明了一个类别名字。

类别能为任何类添加类别,包括不知道源代码的类(例如标准的Cocoa Touch 类等)。

已声明类别的类,类及其子类的所有实例都可以使用声明在类别中的方法,在运行时,通过类别为类添加的方法与类本身的方法没有任何区别。

类别也通常在头文件中进行声明,在分离的源文件中进行类别方法的实现。

为了使用为类添加的类别,需要在使用的地方输入声明类别的头文件。

类别可以作为一种设计模式使用,用来使用类别把一个实现复杂的类分离为几个实现文件。也可以为不同的平台提供不同的类别实现方法。

类别用来声明实例方法或类方法,但不适合声明额外的属性。

在一个类别接口中声明一个属性是有效的,但在类别中声明一个额外的实例变量是不可能的,这意味者编译器不能够生成任何实例变量,也不能够生成任何属性存取方法。
但你能够在类别实现中实现自己的属性存取方法,但你不能够保持和跟踪一个属性值,除非它已经在原先的类中存储。

另外需要注意的是类别中定义的方法名字不能与该类已有的方法或为该类(或其超类)定义的其它类别中的方法冲突。

为已存在类添加带有实例变量的属性的仅有的方法是使用类扩展。

二、类扩展--用来扩展一个类的内部实现

类扩展功能上与类别类似,用来扩展一个类的功能,与类别不同的是,类扩展中能为一个类增加属性和实例变量。另外类扩展仅能在一个有源码的类中使用,用来为其添加功能。使用类扩展通常用来实现和扩展类的私有信息(包括私有属性和方法)。

声明一个类扩展的语法与类别的语法相似,但括号中名字为空,因此类扩展也被称为匿名类别。如下所示:

@interface ClassName ()

@end

类扩展中声明的方法要在原先类的@implementation块中加以实现。

如果在一个类扩展中声明一个属性,编译器自动为其生成相对应的存取方法和一个实例变量。如果在一个类扩展中增加任意方法,它们也必须在类的实现中加以实现。

在一个类扩展中添加定制的实例变量也是可能的。

三、协议

在Objective-C中,每个类都都对外提供自己的接口,类包括接口声明和类实现。而没有像其它语言(如java)那样,接口与类定义是独立的,一个类可以实现多个接口。

但在Objective-C中协议可以起到类似的作用,协议用来声明与任何特定的类独立的方法,如果一个类声明符合某种协议,则其实现中必须实现协议中声明的方法,但与其它语言接口定义不同的是在协议中不仅能声明对象方法,还能声明类方法以及属性。

定义一个协议的语法如下:

@protocol ProtocolName

// list of methods and properties

@end

Objective-C 使用三角括号指示一个属性或类符合一种协议。

默认情况下在一个协议中声明的方法都是必须方法,任何符合该协议的类必须实现这些方法。

在协议中也可以使用@optional关键字规定可选方法。遵从包括可选方法的协议的类可以根据需要实现可选方法或不实现。

@protocol XYZPieChartViewDataSource

- (NSUInteger)numberOfSegments;

- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;

@optional

- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;

- (BOOL)shouldExplodeSegmentAtIndex:(NSUInteger)segmentIndex;

@required

- (UIColor *)colorForSegmentAtIndex:(NSUInteger)segmentIndex;

@end

在以上协议声明中的titleForSegmentAtIndex:和shouldExplodeSegmentAtIndex:方法标记为是可选方法。

@optional关键字指示其下面声明的方法都是可选方法,直到协议定义结束或碰到另外的@required指令。

如果在一个协议中标记一个方法为可选,你必须在试图调用它之前检查是否一个对象实现了该方法。

使用respondsToSelector: 方法使用一个@selector指令引用一个方法的标识(方法名)来检查该方法是否实现。如下所示:

NSString *thisSegmentTitle;

if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {

thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];

}

也可以规定一个协议符合另外的协议,语法如下:

@protocol MyProtocol <NSObject>

...

@end

声明一个类符合一个协议的语法如下:

@interface MyClass : NSObject <MyProtocol>

...

@end

与其它语言一个类可以实现多个接口相同,在Objective-C也可以声明一个类符合多个协议,语法如下:

@interface MyClass : NSObject <MyProtocol, AnotherProtocol, YetAnotherProtocol>

...

@end

但如果出现这种情况,意味着你的类过于复杂,需要重构,分离相关的行为到多个较小的类,每一个类定义清楚的责任。

Objective-C的面向对象特性(二)的更多相关文章

  1. TypeScript入门知识五(面向对象特性二)

    1.泛型(generic) 参数化的类型,一般用来限制集合的内容 class Person { constructor(private name: string) { } work() { }}var ...

  2. 浅谈Objective—C中的面向对象特性

    Objective-C世界中的面向对象程序设计 面向对象称程序设计可能是现在最常用的程序设计模式.如何开发实际的程序是存在两个派系的-- 面向对象语言--在过去的几十年中,很多的面向对象语言被发明出来 ...

  3. Python 基础 面向对象之二 三大特性

    Python 基础 面向对象之二 三大特性 上一篇主要介绍了Python中,面向对象的类和对象的定义及实例的简单应用,本篇继续接着上篇来谈,在这一篇中我们重点要谈及的内容有:Python 类的成员.成 ...

  4. Javascript面向对象特性实现封装、继承、接口详细案例——进级高手篇

    Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript ...

  5. javascript进阶——面向对象特性

    面向对象的javascript是这门语言被设计出来时就考虑的问题,熟悉OOP编程的概念后,学习不同的语言都会发现不同语言的实现是不同的,javascript的面向对象特性与其他具有面向对象特性的语言的 ...

  6. .NET面向对象特性之封装

    .NET面向对象特性之封装 面向对象的基本内容由:类.对象.属性.方法.字段构成. 面向对象的三大特性:继承.多态.封装. 关于面向对象的特性很多人都把目光转向了继承.多态和接口,却很少有人提及过封装 ...

  7. .NET面向对象特性之多态

    .NET面向对象特性之多态 前言 上一篇总结了面向对象三大特性之一的继承,再接再厉,这一章继续总结多态.同时把继承中涉及到多态的内容进一步补充扩展.可以说“继承”是多态的根基.但继承主要关注的是“共通 ...

  8. .NET面向对象特性之“继承”

    整体简介 1.理解继承——继承关系图 2.实现继承与接口多继承 3.new. virtual.override方法 4.抽象方法和抽象类的继承 5.继承的本质 6.继承的复用性.扩展性和安全性 7.多 ...

  9. TypeScript -- 面向对象特性

    .class关键字和类名就可以定义一个类 . 类的访问控制符--有三个,.] = ] = ] = ;.声明参数 .用接口声明方法 .理解模块--一个文件就是一个模块,就是这么个意思 ,不用想的多么高大 ...

  10. 【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态

    一.简介 Lua是一门非常强大.非常灵活的脚本语言,自它从发明以来,无数的游戏使用了Lua作为开发语言.但是作为一款脚本语言,Lua也有着自己的不足,那就是它本身并没有提供面向对象的特性,而游戏开发是 ...

随机推荐

  1. sql server中高并发情况下 同时执行select和update语句死锁问题 (二)

    SQL Server死锁使我们经常遇到的问题,数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁.希望对您学习SQL Server死锁方面能有所帮助. 死锁对于DBA或是数据 ...

  2. 【java多线程系列】java中的volatile的内存语义

    在java的多线程编程中,synchronized和volatile都扮演着重要的 角色,volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的可见性,可见性指的是当一 ...

  3. 【并发编程】AIDL关键字

    oneway Oneway interfaces In early betas, the Android IPC was strictly synchronous. This means that s ...

  4. EBS系统克隆

     术语 克隆是对已有的Oracle应用系统创建一份拷贝的过程.克隆一个Oracle应用系统有几种不同的情况,包括: l   标准克隆 – 复制一个已有的Oracle应用系统生成一份拷贝,例如对生产 ...

  5. Android开发学习之路--Broadcast Receiver之初体验

    学习了Activity组件后,这里再学习下另一个组件Broadcast Receiver组件.这里学习下自定义的Broadcast Receiver.通过按键自己发送广播,然后自己接收广播.新建MyB ...

  6. Uva - 230 - Borrowers

    AC代码: #include <iostream> #include <cstdio> #include <cstdlib> #include <cctype ...

  7. [C++学习历程]基础部分 C++中的函数学习

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/20305815 作者:sushengmiyan 一.静态变量: 局部变量是线程到达定义的 ...

  8. App会取代网站吗?

    本文摘自<程序员的修炼:从优秀到卓越>,购买链接:http://product.china-pub.com/3769829 自1999年以来,不管是作为买家还是卖家,我一直是eBay的热心 ...

  9. Cocos2D:塔防游戏制作之旅(九)

    炮塔哲学:敌人,攻击波和路径点 在创建敌人之前,让我们先为它们"铺路".敌人将沿着一系列的路径点前进,这些路径点互相连接,它们被定义为敌人在你创建的世界中移动的路径. 敌人将在第一 ...

  10. ROS_Kinetic_06 ROS基础内容(三)

    ROS_Kinetic_06 ROS基础内容(三) 先插入一段闲话,关于android的碎片化,无非集中于版本过多,型号各异,品牌杂乱等,似乎这是开源软件无法摆脱的宿命,ROS似乎也在这条路上越走越远 ...