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%10; //取出最后一位;number=number/10;[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合成属性。
1 #import "vehicle.h" 2 @interface Vehicle () 3 @property(nonatomic, strong) NSString *color; 4 -(void) drive:(NSString *)name; 5 @end 6 7 //在实际使用中,通用的做法是省略掉Vehicle_ext.h文件,而是将其中的内容直接添加在Vehicle.m文件@implementation前部即可 8 #import "Vehicle_ext.h" 9 @implementation Vehicle 10 -(void) drive:(NSString *)name 11 { 12 NSLog(@"交通工具名称%@,颜色属性%@",_name,_color); 13 } 14 @end
5、协议(protocol)是OC的一个重要知识点,其作用类似于Java中的接口,用于定义多个类应该遵循的规范。协议提提供任何实习那,协议体现的是规范和实现分离的松耦合的设计哲学。
协议定义的是多个类共同的公共行为规范,这些行为是与外部交流的通道,这就意味着协议里通常是定义一组公用方法,但是不会为这些方法提供实现,方法的实现则交给类去完成。协议定义时使用@protocol关键字,在协议中还有两个关键字@optional and @required,@optional 声明的方法可以实现,也可以不实现。@required声明的方法必须实现。具体语法格式如下:
// 定义的协议名称 遵守协议名称 @protocol MyProtocol <NSObject> @required //定义必选方法 @optional //定义可选方法@end//使用协议 @interface 类名 :父类 <协议1,协议2 ... >
- 一个协议可以有多个直接父协议,但协议只能继承协议,不能继承类
- 学一种定义的方法只有方法签名,没有实现。协议中的方法既可以是类方法,也可以是实例方法。
1 // 2 // Women.h 3 // 正式协议的定义 4 // 5 // Created by Goddog on 15/1/11. 6 // Copyright (c) 2015年 Goddog. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @protocol Women <NSObject> 12 //定义协议的方法 13 @optional //可以不实现该接口的方法 14 -(void) pretty; 15 @required //必须实现该接口的方法 16 -(void) beautiful:(NSString*) count; 17 @end
正式协议的定义Women.h
1 // 2 // Man.h 3 // 正式协议的定义 4 // 5 // Created by Goddog on 15/1/11. 6 // Copyright (c) 2015年 Goddog. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @protocol Man <NSObject> 12 //定义协议的方法 13 -(void) handsome; 14 @end
正式协议的定义 Man.h
![](/assets/blank.gif)
![](/assets/blank.gif)
1 // 2 // Person.h 3 // 正式协议的定义 4 // 5 // Created by Goddog on 15/1/11. 6 // Copyright (c) 2015年 Goddog. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import "Women.h" 11 #import "Man.h" 12 13 //协议继承了Women、Man协议 14 @protocol Person <Women,Man> 15 //定义协议的方法 16 -(NSString*) play; 17 @end
正式协议的定义Person.h
![](/assets/blank.gif)
![](/assets/blank.gif)
1 // 2 // SuperMan.h 3 // 正式协议的定义 4 // 5 // Created by Goddog on 15/1/11. 6 // Copyright (c) 2015年 Goddog. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import "Person.h" 11 12 @interface SuperMan : NSObject<Person> //实现Person的协议 13 14 @end
协议的使用SuperMan.h
![](/assets/blank.gif)
![](/assets/blank.gif)
1 // 2 // SuperMan.m 3 // 正式协议的定义 4 // 5 // Created by Goddog on 15/1/11. 6 // Copyright (c) 2015年 Goddog. All rights reserved. 7 // 8 9 #import "SuperMan.h" 10 #define MAX_CACHE_LINE 10 11 12 @implementation SuperMan 13 { 14 NSString* playData[MAX_CACHE_LINE]; //使用数组记录所有需要缓存的数据 15 int dataNum; //记录当前的数量 16 } 17 18 //实现协议方法 19 -(void) pretty 20 { 21 //只要还有漂亮的,继续上 22 while (dataNum > 0) { 23 NSLog(@"正在和%@玩%@",playData[0],[self play]); 24 //剩下的人数减少 25 dataNum --; 26 //把列队整体向前移 27 for (int i = 0; i < dataNum; i++) { 28 playData[i] = playData[i + 1]; 29 } 30 } 31 } 32 33 //实现协议方法 34 -(void) beautiful:(NSString *)count 35 { 36 if (dataNum >= MAX_CACHE_LINE) { 37 NSLog(@"人数已满,不要在上了!"); 38 } 39 else 40 { 41 //把人数添加到列队中 42 playData[dataNum++] = count; 43 } 44 } 45 46 //实现协议方法 47 -(void) handsome 48 { 49 NSLog(@"英俊"); 50 } 51 52 //实现协议方法 53 -(NSString*) play 54 { 55 56 return @"游戏"; 57 } 58 59 @end
类的实现SuperMan.m
![](/assets/blank.gif)
![](/assets/blank.gif)
1 #import <Foundation/Foundation.h> 2 #import "SuperMan.h" 3 4 int main(int argc, const char * argv[]) { 5 @autoreleasepool { 6 //创建超人对象 7 SuperMan* superMan = [[SuperMan alloc] init]; 8 //调用协议的方法 9 [superMan beautiful:@"乌克兰美女"]; 10 [superMan beautiful:@"白俄罗斯美女"]; 11 [superMan pretty]; 12 [superMan handsome]; 13 14 //创建超人对象,当成Man使用 15 NSObject<Man>* man = [[SuperMan alloc] init]; 16 //调用Man协议中定义的方法 17 [man handsome]; 18 19 //创建超人对象,当成Women使用 20 id<Women> women = [[SuperMan alloc] init]; 21 //调用Women协议中定义的方法 22 [women beautiful:@"俄罗斯美女"]; 23 [women pretty]; 24 //[women handsome];//这样是不能调用的 25 } 26 return 0; 27 }
类的调用main.m
转载于:https://www.cnblogs.com/mukekeheart/p/7357437.html
OC学习7——类别、扩展和协议相关推荐
- 【IOS 开发】Objective - C 面向对象高级特性 - 包装类 | 类处理 | 类别 | 扩展 | 协议 | 委托 | 异常处理 | 反射
一. Objective-C 对象简单处理 1. 包装类 (1) 包装类简介 NSValue 和 NSNumber : -- 通用包装类 NSValue : NSValue 包装单个 short, i ...
- OC学习笔记之006面向对象包装类,协议
1.包装类NSValue和NSNumber NSValue是NSNumber的父类,NSNumber是更具体的包装类,包装各种数值类型,主要有三类方法 +numberWithXXX:类方法,直接将特定 ...
- 学习 PHP SOAP 扩展的一些笔记
对 SOAP 的相关学习就先告此一段落,这是最后一篇文章用来记录下学习过程中的一些笔记和心得. 前面三篇文章分别是: <SOAP 介绍> <SOAP Web 服务介绍> < ...
- 对扩展openflow协议的一点思考
软件定义X变得越来越火,正所谓,Software is eating the world. 软件定义网络也是如此.不论是在工业界还是学术界都将是一次伟大的革命,都在紧随着这个行业的方向,找自 ...
- 类别,非正式协议,正式协议
类别,非正式协议,正式协议 1类别: 1.1 不能添加新的实例变量 1.2 如果一定要在类别中使用实例标量,可以使用全局变量 关联 额外变量 注:Cocoa中没有任何真正的私有方法,只要知道对象支持的 ...
- 《STM32从零开始学习历程》——CAN通讯协议协议层
<STM32从零开始学习历程>@EnzoReventon CAN通讯协议协议层 相关链接: <STM32从零开始学习历程>--CAN通讯协议物理层 CAN-bus规范 V2.0 ...
- 基于局域网的扩展认证协议EAPOL Extensible Authentication Protocol
EAP是Extensible Authentication Protocol的缩写. EAP是一个普遍使用的认证机制,它常被用于无线网络或点到点的连接中.EAP不仅可以用于无线局域网,而且可以用于有线 ...
- 学习Kotlin(六)扩展与委托
推荐阅读: 学习Kotlin(一)为什么使用Kotlin 学习Kotlin(二)基本语法 学习Kotlin(三)类和接口 学习Kotlin(四)对象与泛型 学习Kotlin(五)函数与Lambda表达 ...
- CoAP协议学习笔记 3.1 CoAP协议翻译 加密基础介绍
CoAP协议学习笔记可点此查看. 1 前言 在之前的学习中,没有过多关注加密.但实际部分厂家的IoT平台(阿里云.OneNET)已经启用了相关安全处理,有必要深入学习下. 在 CoAP 协议 RFC7 ...
最新文章
- Ubuntu下使用CMake编译OpenSSL源码操作步骤(C语言)
- 一张象限图引发的血案
- 3. nginx的请求转发算法,如何配置根据权重转发
- csp2020 j2民间数据下载_华为麒麟 990 5G 下载速率领先
- php mysql八大动态w...,PHP+MySQL八大动态Web应用实战
- tcpdump -i eth0 -n -vvv src or dst port 443
- SQLServer链接服务器至Oracle
- 各种损失损失函数的使用场景和使用方法:KL散度
- 动态规划在求解传递闭包问题中的应用(JAVA)--Warshell算法
- aba问题mysql_面试题总结:可能是全网最好的MySQL重要知识点
- dbeaver can't connect HBase1.2 using phoenix driver #1863
- 【C语言】04-函数
- 用手机otg方式给U盘制作一个Win10PE启动U盘,手机加U盘协助电脑重装系统
- windows微信协议|PC微信协议829版
- nsstring sizewithfont的崩溃
- C++链接报错:which may bind externally can not be used when making a shared object; recompile with -fPIC
- 毕业了,等待我们的是什么?
- 国外10款开源的HTML 5小游戏
- sqlmap之sql注入(一)
- ipv4与ipv6的联系与区别
热门文章
- JavaFX maven工程pom文件完整内容
- Go语言web框架beego:目录说明
- linux随机数示例:随机产生以139开头的电话号码
- Spring Boot 2.x整合Apollo代码示例
- Python Django URL逆向解析(通过Python代码逆向访问)代码示例
- springboot @PropertySource+@Value注入properties配置文件属性值
- @PropertySource与@ConfigurationProperties多种方式读取配置文件详解,附带@PropertySources使用说明
- prometheus和grafana、node_exporter监控服务资源
- Qt for ios 设置程序图标(logo)和启动页(splash)
- 程序员生存定律--程序人生的出口