OC学习7——类别、扩展和协议
1、我么在调用NSLog()方法打印一个对象时,实际上是调用了该对象的description方法,这个description方法就和Java中的toString()方法一样。所以,下面两行代码其实是一样的
NSLog(@"%@", p) ; NSLog(@"%@", [p description]) ;
description方法是NSObject类的一个实例方法,所有的OC都是NSObject类的子类,因此,所有的类都有description方法。description方法方法通常用于实现这样的一个功能:当程序员直接打印该对象时,系统将会输出该对象的“自我描述”信息,用以告诉外界该对象具有的状态信息。NSObject类提供的description方法总是返回<FKPerson:十六进制的首地址>,这个返回值并不是先自我描述的功能,因此,如果用户需要自定义类实现自我描述的功能,则必须重写NSObject类的description方法。
2、==与isEqual()方法的区别(这一点与Java中的异同点是一致的):
- ==:如果是比较对象是两个基本类型,则数值相同就返回true,不同则返回false。如果比较对象是两个指针变量,则如果两个指针都指向同一个对象则返回true,否则返回false。
- isEqual():该方法是NSObject类提供的一个实例方法,因此所有指针变量都可以调用这个方法来判断是否与其他指针变量相等。在默认情况下,isEqual()的判断方法和==一样。如果希望采用自定义的相等标准,则可以通过重写isEqual()方法来实现。NSString已经重写了isEqual()方法,NSString的isEqual()方法判断两个字符串相等的标准是:只要两个字符串包含的所有的字符序列相同,则isEqual()返回true,否则返回false。
3、OC中没有像Java和C++那样提供抽象类的语法支持,而在实际项目开发中,总有需要用到抽象类的时候,此时就会选择定义一个父类,并以该父类派生出多个子类,其他程序使用这些类时,实际上返回的是子类的实例,这一系列的类被称为一个类簇(cluster),这个父类就模拟了抽象类的功能。
OC的动态特性允许使用类别(category)为现有的类添加新房,并且不需要创建子类,不需要访问原有类的代码。通过使用类别就可以动态地为现有的类添加新方法,而且可以将类定义模块化地分不到多个文件中。类别同样由接口和实现部分组成,接口和实现部分语法格式如下:
@interface 已有类 (类别名)
//方法定义,类别中只能添加方法,不能添加成员变量
。。。
@end @implementation已有类 (类别名)
//方法实现
。。。
@end
- 类别名的命名很随意,我们自己取定就可以,一般用于描述增加部分的功能
- 通过类别为制定的类添加新方法之后,这个新方法不仅会影响到该类,还会影响到该类的所有子类,每个子类都会获得类别扩展的方法。
- 可根据需要为一个类定义多个类别,不同的类别都可对原有的类增加方法的定义。
- 就编程习惯而言,一般习惯将类别的接口文件命名为“类名+类别名.h”的形式,同样,实现文件则命名位“类名+类别名.m”的形式。
//接口部分
#import <Foundation/Foundation.h> @interface NSArray (Convert) +(NSMutableArray *)arrayFormNumber:(int)number; @end //实现部分
#import "NSArray+Convert.h" @implementation NSArray (Convert) +(NSMutableArray *)arrayFormNumber:(int)number{
NSMutableArray *numberArray=[[NSMutableArray alloc]init];
while (number) {
int last=number%; //取出最后一位;
number=number/;
[numberArray addObject:[NSNumber numberWithInt:last]];
}
return [numberArray autorelease];
} @end - 使用类别可以对类进行模块化设计:在前面类的设计中,类的接口部分在.h文件中定义,类的实现部分在.m文件中定义,且类的实现不能分布到多个.m文件中。但是当某个类特别大时,如果将所有实现都放在一个.m文件中,将会导致这个文件非常大,以至于维护起来非常困难。如果将一个较大的类进行分模块设计,使用类别是一个不错的选择。例如NSWindow类就采用这种设计思想,具体可以在xcode上查看NSWindow.h文件。
- 使用类别来实现私有方法的调用:OC中实际上并没有真正的是有方法,通常而言所说的私有方法指的是没有在接口部分定义而在实现部分定义的方法,这类方法是不允许被调用的,因为没有通过接口部分向外暴露调用接口。在OC中,除了通过NSObject类的performSelector()来执行动态调用从而实现调用私有方法之外,我们还可以通过使用类别来定义前向引用(其实就是通过类别在接口部分补充定义之前未定义的私有方法),从而实现对私有方法的调用。
4、OC中的扩展(extension)和类别相似,扩展相当于匿名类别,不同的是扩展可以定义实例变量。定义扩展的语法格式如下:
@interface 已有类 ()
{
//定义实例变量
}
//方法定义
。。。
@end
- 在语法上,扩展相当于匿名类别。但是在用法上,类别通常是有单独的.h和.m文件,而扩展则用于临时对某一个类的接口进行扩展,类实现部分同时实现类接口部分和扩展中定义的方法。
- 在类的扩展中,可以额外增加实例变量,也可以用@property来合成属性,但是在定义类别是则不允许定义成员变量,也不能用@property合成属性。
#import "vehicle.h"
@interface Vehicle ()
@property(nonatomic, strong) NSString *color;
-(void) drive:(NSString *)name;
@end //在实际使用中,通用的做法是省略掉Vehicle_ext.h文件,而是将其中的内容直接添加在Vehicle.m文件@implementation前部即可
#import "Vehicle_ext.h"
@implementation Vehicle
-(void) drive:(NSString *)name
{
NSLog(@"交通工具名称%@,颜色属性%@",_name,_color);
}
@end
5、协议(protocol)是OC的一个重要知识点,其作用类似于Java中的接口,用于定义多个类应该遵循的规范。协议提提供任何实习那,协议体现的是规范和实现分离的松耦合的设计哲学。
协议定义的是多个类共同的公共行为规范,这些行为是与外部交流的通道,这就意味着协议里通常是定义一组公用方法,但是不会为这些方法提供实现,方法的实现则交给类去完成。协议定义时使用@protocol关键字,在协议中还有两个关键字@optional and @required,@optional 声明的方法可以实现,也可以不实现。@required声明的方法必须实现。具体语法格式如下:
// 定义的协议名称 遵守协议名称
@protocol MyProtocol <NSObject> @required
//定义必选方法 @optional
//定义可选方法 @end //使用协议
@interface 类名 :父类 <协议1,协议2 ... >
- 一个协议可以有多个直接父协议,但协议只能继承协议,不能继承类
- 学一种定义的方法只有方法签名,没有实现。协议中的方法既可以是类方法,也可以是实例方法。
//
// Women.h
// 正式协议的定义
//
// Created by Goddog on 15/1/11.
// Copyright (c) 2015年 Goddog. All rights reserved.
// #import <Foundation/Foundation.h> @protocol Women <NSObject>
//定义协议的方法
@optional //可以不实现该接口的方法
-(void) pretty;
@required //必须实现该接口的方法
-(void) beautiful:(NSString*) count;
@end正式协议的定义Women.h
//
// Man.h
// 正式协议的定义
//
// Created by Goddog on 15/1/11.
// Copyright (c) 2015年 Goddog. All rights reserved.
// #import <Foundation/Foundation.h> @protocol Man <NSObject>
//定义协议的方法
-(void) handsome;
@end正式协议的定义 Man.h
//
// Person.h
// 正式协议的定义
//
// Created by Goddog on 15/1/11.
// Copyright (c) 2015年 Goddog. All rights reserved.
// #import <Foundation/Foundation.h>
#import "Women.h"
#import "Man.h" //协议继承了Women、Man协议
@protocol Person <Women,Man>
//定义协议的方法
-(NSString*) play;
@end
正式协议的定义Person.h
//
// SuperMan.h
// 正式协议的定义
//
// Created by Goddog on 15/1/11.
// Copyright (c) 2015年 Goddog. All rights reserved.
// #import <Foundation/Foundation.h>
#import "Person.h" @interface SuperMan : NSObject<Person> //实现Person的协议 @end
协议的使用SuperMan.h
//
// SuperMan.m
// 正式协议的定义
//
// Created by Goddog on 15/1/11.
// Copyright (c) 2015年 Goddog. All rights reserved.
// #import "SuperMan.h"
#define MAX_CACHE_LINE 10 @implementation SuperMan
{
NSString* playData[MAX_CACHE_LINE]; //使用数组记录所有需要缓存的数据
int dataNum; //记录当前的数量
} //实现协议方法
-(void) pretty
{
//只要还有漂亮的,继续上
while (dataNum > ) {
NSLog(@"正在和%@玩%@",playData[],[self play]);
//剩下的人数减少
dataNum --;
//把列队整体向前移
for (int i = ; i < dataNum; i++) {
playData[i] = playData[i + ];
}
}
} //实现协议方法
-(void) beautiful:(NSString *)count
{
if (dataNum >= MAX_CACHE_LINE) {
NSLog(@"人数已满,不要在上了!");
}
else
{
//把人数添加到列队中
playData[dataNum++] = count;
}
} //实现协议方法
-(void) handsome
{
NSLog(@"英俊");
} //实现协议方法
-(NSString*) play
{ return @"游戏";
} @end
类的实现SuperMan.m
#import <Foundation/Foundation.h>
#import "SuperMan.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
//创建超人对象
SuperMan* superMan = [[SuperMan alloc] init];
//调用协议的方法
[superMan beautiful:@"乌克兰美女"];
[superMan beautiful:@"白俄罗斯美女"];
[superMan pretty];
[superMan handsome]; //创建超人对象,当成Man使用
NSObject<Man>* man = [[SuperMan alloc] init];
//调用Man协议中定义的方法
[man handsome]; //创建超人对象,当成Women使用
id<Women> women = [[SuperMan alloc] init];
//调用Women协议中定义的方法
[women beautiful:@"俄罗斯美女"];
[women pretty];
//[women handsome];//这样是不能调用的
}
return ;
}
类的调用main.m
OC学习7——类别、扩展和协议的更多相关文章
- swift学习笔记4——扩展、协议
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
- OC学习笔记——类别(Category)
类别,有些程序员又称之为分类. 类别是一种为现有的类添加新方法的方式,尤其是为系统的做扩展的时候,不用继承系统类,可以直接为类添加新的方法.也可以覆盖系统类的方法. 如: @interface NSO ...
- Snail—OC学习之类别Category
类别就是向类加入一些实用的功能或者方法 利于开发 类能够是系统类.能够是自己定义类 类别跟子类是不一样的.类别仅仅能加入一些方法 属性变量什么的不能够加入 不创建新类,就可以对已有类进行扩展 做项目的 ...
- 【IOS 开发】Objective - C 面向对象高级特性 - 包装类 | 类处理 | 类别 | 扩展 | 协议 | 委托 | 异常处理 | 反射
一. Objective-C 对象简单处理 1. 包装类 (1) 包装类简介 NSValue 和 NSNumber : -- 通用包装类 NSValue : NSValue 包装单个 short, i ...
- OC学习9——反射机制
1.OC提供了3种编程方式与运行环境进行交互: 直接通过OC的源代码:这是最常见的方式,开发人员只是编写OC源代码,而运行环境负责在后台工作. 通过NSObject类中定义的方法进行动态编程:因为绝大 ...
- IOS中类的扩展(协议,分类)
IOS中类的扩展(协议,分类) 扩展类,我们可以使用协议和分类这两种方法,下面我们来分别实现这两种方法: 参考网址:http://www.cnblogs.com/wendingding/p/37095 ...
- IOS开发-OC学习-常用功能代码片段整理
IOS开发-OC学习-常用功能代码片段整理 IOS开发中会频繁用到一些代码段,用来实现一些固定的功能.比如在文本框中输入完后要让键盘收回,这个需要用一个简单的让文本框失去第一响应者的身份来完成.或者是 ...
- OC学习16——对象归档
转载自 OC学习篇之---归档和解挡 OC中的归档就是将对象写入到一个文件中,Java中的ObjectInputStream和ObjectOutputStream来进行操作的.当然在操作的这些对象都 ...
- OC学习6——面相对象的三大特性
我们在学习Java的时候都知道,类有三大特性:继承,封装,多态,这也是面向对象的三大特征.OC学习篇之---类的三大特性(封装,继承,多态) 1.封装(Encapsulation)是指将对象的状态信息 ...
随机推荐
- django作业2
管理后台 1.登陆Form 2.Session (用装饰器实现) 3.装饰器 4.主机,主机组 添加(主机,主机组) 删除 修改 查询
- cocos2dx3.0导出自定义类到lua的方法详细步骤
我写了一个用3.0的工具导出类到lua,自动生成代码的方法. 以前要导出c++类到lua,就得手动维护pkg文件,那简直就是噩梦,3.0以后就会感觉生活很轻松了. 下面我就在说下具体做法.1.安装必要 ...
- Oracle的窗口和自动任务
Oracle数据库自己会例行做一些定时任务,比如会自动进行统计信息收集等作业任务.如果统计信息收集的时间正好赶上业务的高峰期,那就有可能由此引发一系列性能故障. 那么,我们该如何查看这些数据库自动去做 ...
- 12. ZooKeeper配额和认证
ZooKeeper具有与其数据模型相关的可配置配额(quota). 可以设置znode上的配额限制和存储的数据量.如果ZooKeeper命名空间中的一个子树超出与其关联的配额,ZooKeeper会在日 ...
- python利用scrapy框架爬取起点
先上自己做完之后回顾细节和思路的东西,之后代码一起上. 1.Mongodb 建立一个叫QiDian的库,然后建立了一个叫Novelclass(小说类别表)Novelclass(可以把一级类别二级类别都 ...
- Thinkphp导入外部类的方法
相信很多人在使用TP时候都苦恼使用外部类各种不成功 下面为大家详细介绍下引用方法和注意细节 手动加载第三方类库 由于第三发类库没有具体的命名空间,所以需要使用以下几种方法手动导入 1.import方法 ...
- [C#]使用Gembox.SpreadSheet向Excel写入数据及图表
本文为原创文章.源代码为原创代码,如转载/复制,请在网页/代码处明显位置标明原文名称.作者及网址,谢谢! 开发工具:VS2017 语言:C# DotNet版本:.Net FrameWork 4.0及以 ...
- django框架中的form组件的用法
form组件的使用 先导入: from django.forms import Form from django.forms import fields from django.forms impor ...
- yum中$releasever、 $basearch等变量含义
[root@kickstart ~]# rpm -qf /etc/redhat-release centos-release--4.1708.el7.centos.x86_64 yum中的$relea ...
- Hibernate框架进阶(中篇)之多表关系
导读 Hibernate进阶主要分为上中下三篇,本文是中篇,主要讲解Hibernate框架中多表关系的实现.我们知道多表关系有一对一.一对多(多对一)和多对多三种关系.而1对1关系一般合并为一个表处理 ...