Objective-C——Message(消息)、Category(分类) 、Protocol(协议) 总结

cmake注释和message用法分析 cmake注释和message基础 阅读详情

Ojbective-C的语法设计主要基于Smalltalk,除了提供传统的面向对象编程特性之外,还增加了很多类似动态语言Ruby、Python才具有的特性,例如动态类型、动态加载、动态绑定等等,同时强化了消息传递机制和表意(Intention Revealing Interface)接口的概念。

 

—消息—

消息传递模型(Message Passing)是Objective-C语言的核心机制。在Objective-C中,没有方法调用这种说法,只有消息传递。在C++或Java中调用某个类的方法,在Objective-C中是给该类发送一个消息。在C++或Java里,类与类的行为方法之间的关系非常紧密,一个方法必定属于一个类,且于编译时就已经绑定在一起,所以你不可能调用一个类里没有的方法。而在Objective-C中就比较简单了,类和消息之间是松耦合的,方法调用只是向某个类发送一个消息,该类可以在运行时再确定怎么处理接受到的消息。也就是说,一个类不保证一定会响应接收到的消息,如果收到了一个无法处理的消息,那么程序就是简单报一个错。甚至你可以向一个值为nil的空对象发送消息,系统都不会出错或宕掉。这种设计本身也比较符合软件的隐喻。

 

在表意接口(Intention Revealing Interface)方面,Objective-C也是设计的比较出色的语言。面向对象语言的特性之一就是通过API把实现封装起来,为上层建筑提供服务。但是需要注意的一点就是,你封装的API最好能够让调用者看到接口描述就知道怎么使用。如果为了使用一个API必须要去研究它的实现,那么就失去了封装的意义。Objective-C通过显式的API描述,让开发者不自觉的写出满足表意接口的API,比如下图中的API描述。

下面我们来说说多态和继承。

 与Java一样,Objective-C一样不支持多重继承,但是通过类别(Category)和协议(Protocol)可以很好的实现代码复用和扩展。

 

—Category—

首先我们来谈谈Category。

 

Objective-C提供了一种与众不同的方式——Category,可以动态的为已经存在的类添加新的行为。这样可以保证类的原始设计规模较小,功能增加时再逐步扩展。使用Category对类进行扩展时,不需要访问其源代码,也不需要创建子类。Category使用简单的方式,实现了类的相关方法的模块化,把不同的类方法分配到不同的分类文件中。

 

实现起来很简单,我们举例说明。

SomeClass.h
@interface SomeClass : NSObject{
}
-(void) print;
@end 


这是类SomeClass的声明文件,其中包含一个实例方法print。如果我们想在不修改原始类、不增加子类的情况下,为该类增加一个hello的方法,只需要简单的定义两个文件SomeClass+Hello.h和SomeClass+Hello.m,在声明文件和实现文件中用“()”把Category的名称括起来即可。声明文件代码如下:

#import "SomeClass.h"
 
@interface SomeClass (Hello)
-(void)hello;
@end

实现文件代码如下

#import "SomeClass+Hello.h"
@implementation SomeClass (Hello)
-(void)hello{
    NSLog (@"name:%@ ", @"Jacky");
}
@end 

其中Hello是Category的名称,如果你用XCode创建Category,那么需要填写的内容包括名称和要扩展的类的名称。这里还有一个约定成俗的习惯,将声明文件和实现文件名称统一采用“原类名+Category”的方式命名。

调用也非常简单,毫无压力,如下:

首先引入Category的声明文件,然后正常调用即可。

#import "SomeClass+Hello.h"
 
SomeClass * sc =[[SomeClass alloc] init];
[sc hello] 

执行结果是:

name:Jacky 

 

Category的使用场景:

1、当你在定义类的时候,在某些情况下(例如需求变更),你可能想要为其中的某个或几个类中添加方法。

2、一个类中包含了许多不同的方法需要实现,而这些方法需要不同团队的成员实现

3、当你在使用基础类库中的类时,你可能希望这些类实现一些你需要的方法。

 

遇到以上这些需求,Category可以帮助你解决问题。当然,使用Category也有些问题需要注意,

1、Category可以访问原始类的实例变量,但不能添加变量,如果想添加变量,可以考虑通过继承创建子类。

2、Category可以重载原始类的方法,但不推荐这么做,这么做的后果是你再也不能访问原来的方法。如果确实要重载,正确的选择是创建子类。

3、和普通接口有所区别的是,在分类的实现文件中可以不必实现所有声明的方法,只要你不去调用它。

 

用好Category可以充分利用Objective-C的动态特性,编写出灵活简洁的代码。

 

—Protocol— 

下面我们再来看Protocol。

Protocol,简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现。这种模式一般称为代理(delegation)模式。你通过Protocol定义各种行为,在不同的场景采用不同的实现方式。在iOS和OS X开发中,Apple采用了大量的代理模式来实现MVC中View和Controller的解耦。

 

定义Protocol很简单,在声明文件(h文件)中通过关键字@protocol定义,然后给出Protocol的名称,方法列表,然后用@end表示Protocol结束。在@end指令结束之前定义的方法,都属于这个Protocol。例如:

@protocol ProcessDataDelegate <NSObject>
@required
- (void) processSuccessful: (BOOL)success;

@optional
- (id) submitOrder: (NSNumber *) orderid;
@end

以上代码可以单独放在一个h文件中,也可以写在相关类的h文件中,可以视具体情况而定。该Protocol包含两个方法,processSuccessful和submitOrder。这里还有两个关键字,@required和@optional,表示如果要实现这个协议,那么processSuccessful方法是必须要实现的,submitOrder则是可选的,这两个注解关键字是在Objective-C 2.0之后加入的语法特性。如果不注明,那么方法默认是@required的,必须实现。

 

那么如何实现这个Protocol呢,很简单,创建一个普通的Objective-C类,取名为TestAppDelegate,这时会生成一个h文件和m文件。在h文件中引入包含Protocol的h文件,之后声明采用这个Protocol即可,如下:

@interface TestAppDelegate : NSObject<ProcessDataDelegate>;

@end

用尖括号(<...>)括起来的ProcessDataDelegate就是我们创建的Protocol。如果要采用多个Protocol,可以在尖括号内引入多个Protocol名称,并用逗号隔开即可。例如<ProcessDataDelegate,xxxDelegate>

 

m文件如下:

@implementation TestAppDelegate

- (void) processSuccessful: (BOOL)success{
    if (success) {
        NSLog(@"成功");
    }else {
        NSLog(@"失败");
    }
}

@end 

由于submitOrder方法是可选的,所以我们可以只实现processSuccessful。

 

Protocol一般使用在哪些场景呢?Objective-C里的Protocol和Java语言中的接口很类似,如果一些类之间没有继承关系,但是又具备某些相同的行为,则可以使用Protocol来描述它们的关系。不同的类,可以遵守同一个Protocol,在不同的场景下注入不同的实例,实现不同的功能。其中最常用的就是委托代理模式,Cocoa框架中大量采用了这种模式实现数据和UI的分离。例如UIView产生的所有事件,都是通过委托的方式交给Controller完成。根据约定,框架中后缀为Delegate的都是Protocol,例如UIApplicationDelegate,UIWebViewDelegate等,使用时大家可以留意一下,体会其用法。

 

使用Protocol时还需要注意的是:

1、Protocol本身是可以继承的,比如:

@protocol A
     -(void)methodA;
@end
@protocol B <A>
     -(void)methodB;
@end

如果你要实现B,那么methodA和methodB都需要实现。 

2、Protocol是类无关的,任何类都可以实现定义好的Protocol。如果我们想知道某个类是否实现了某个Protocol,还可以使用conformsToProtocol进行判断,如下:

[obj conformsToProtocol:@protocol(ProcessDataDelegate)] 

好吧,具体的语言特性这次就介绍这么多。从某种意义上来说,Objective-C是一门古老的语言,发明于1980年。1988年,乔布斯的Next公司获得了Objective-C语言的授权,并开发出了Objective-C的语言库和NEXTSTEP的开发环境。NextStep是以Mach和BSD为基础,Objective-C是其语言和运行库,后来的事大家都清楚,苹果买了Next,乔布斯回归苹果,开始神奇的苹果振兴之路,NextStep成了Max OS X的基础。以后发展越来越好,Objctive-C成了Apple的当家语言,现在基本上是Apple在维护Objctive-C的发展。

 

在苹果的AppStore推出之前,Objective-C一直相对小众,但是其优秀的语言特性似乎一直在为后面的爆发积蓄力量,当苹果平台级的应用出现之后,Objective-C开始大放异彩,静态语言的效率和动态语言的特性得到众多程序员的喜爱,目前它已经以火箭般的速度蹿升TIOBE语言排行版第四位。







9 HAL库驱动框架简述(STM32HAL库) HAL库外设的使用步骤总结如下:1、定义并填充xxx外设句柄结构体。2、如果遵循HAL库规范,通过HAL_xxx_MspInit()函数,实现外设底层资源的初始化,包括但不限于GPIO、时钟、DMA、中断等资源的初始化。3、调用HAL库的对应外设初始化函数,形如:HAL_xxx_Init()。4、初始化完成,开始使用外设。5、使用方法具体查看对应外设的HAL库驱动包中的说明:补充:HAL库使用主线外设初始化外设使用。 阅读详情

相关推荐

(HAL)stm32f407+freertos通过usb驱动移远4G模块-EC600U

文章记录了stm32cubemx+stm32f407+freertos+usb host实现移远4G模块EC600U的usb驱动的调试过程,usb host cdc库的使用和遇到的问题及解决办法。

gongrulin的博客 3899

C可变参数用法以及自己的Message()函数

首先,关于可变参数,实际上,也就是未知参数个数,在调用的时候再解析。我的理解是C总会把参数放到函数堆栈,那么,虽然声明函数 的时候不知道参数个数,但可以在使用时指明,并根据指出的参数进行解析,操作。 解析这种参数使用va_list宏,用法如下:  1. 声明va_list,  2. 使用va_start()取得参数"..."地址

wdt3385的专栏 1443

ABAP代码使用OAuth2.0 Client Credential调用外部API

ABAP-OAuth2.0-调用外部API

m0_74015269的博客 1956

C语言:Message类

message.h #ifndef MESSAGE_H #define MESSAGE_H #define TRUE 1 #define FALSE 0 typedef struct { int sender; int isSend; int isCharge; char date[8]; }Message; Message *...

weixin_34290631的博客 1545

从零到一:ArduPilot无人船PID调参实战指南

本文详细介绍了ArduPilot无人船PID调参的实战指南,从基础参数设定到高级调参技术,帮助用户掌握水面环境下的PID控制逻辑。通过案例分析和参数示例,解决无人船在空载、负载变化及不同水域环境中的航行问题,提升无人船的稳定性和精确度。

weixin_29266647的博客 506

ArcGIS图解建模工具与DEM提取山脊、山谷线(水文分析、表面分析)

参考汤国安、杨昕等编著的《地理信息系统空间分析实验教程第二版》 利用水文分析(流量)和表面分析(坡向变率)得到山脊和山谷线 文章目录1、基本概念1.1 正地形1.2 负地形正负地形的影响2、水文分析方法2.1 基本思想原理2.2 技术路线2.3 操作步骤2.3.1 正负地形的提取2.3.2 利用水文分析思想和工具提取研究区域的山脊线2.3.3 利用水文分析思想和工具提取研究区域的山谷线2.3.4 利用水文分析提取山脊线和山谷线结果3、表面分析方法3.1 基本思想原理3.2 技术路线3.3 操作步骤4、图.

fungis 1万+

c语言message函数,C语言:Message类

message.h#ifndef MESSAGE_H#define MESSAGE_H#define TRUE 1#define FALSE 0typedef struct {int sender;int isSend;int isCharge;char date[];}Message;Message * makeMessage(const int sender, const char *date...

weixin_29789925的博客 3121

海康视觉脚本开发全流程解析

本文详细解析了海康机器视觉平台(VM)中脚本模块的开发全流程。从创建第一个脚本模块入手,深入讲解了输入参数、输出参数与内部变量的定义与区别,并提供了C#脚本编写、公用函数调用、代码结构组织以及编译调试的实用指南。旨在帮助开发者掌握海康视觉脚本开发的核心技巧,高效实现复杂的自定义视觉逻辑处理。

beer8的博客 602

CMessage(提示)

// // CMessage.h // myGame1 // // Created by zctech on 14-2-26. // // #ifndef __myGame1__CMessage__ #define __myGame1__CMessage__ #include #include "cocos2d.h" #include "CResource.h" class CMes

zwcwu31的专栏 2002

【数据库】银行/信贷业务测试工作中涉及的数据库表格

银行/信贷业务测试工作中涉及的数据库表格,金融信贷测试人必看!

孤之鹜的博客 1169

innovus:给channel加soft blockage

dbGet [dbGet top.fplan.pBlkgs.name finishfp_place_blkg_* -p].boxes就可以获得channel坐标。意思是给30um以下的channel加soft blk,至于channel的坐标,通过抓取该soft blk去获取,比较容易。工具自己加入的placement blockage命名上叫finishfp_place_blkg_*ICC2中有给channel自动加soft blockage的命令,相应的innovus也有类似的命令,我们可以使用。

m0_61544122的博客 481

iOS------消息、Category和protocol

iOS——消息、Category和protocol消息消息传递模型(Message Passing)是Objective-C语言的核心机制。在Objective-C中,没有方法调用的说话,都是通过消息传递。在c++或java中调用某个类的方法,在Objective-C是给该类发送一个方法。在oc中,类与消息之间是松耦合的,方法调用只是向某一个类发送一条消息,该类可以在运行时再确定怎么处理接收到的消息

TendeRneSs.宸的博客 529

⭐️VMwareWorkstation17.0虚拟机安装搭建Windows 7虚拟机(完整图文详细步骤含配置VMware Tools教程)

本教程为大家提供了从安装VMware Workstation 17.0开始,到在虚拟机上成功搭建Windows 7专业版系统的完整步骤。我们详细介绍了准备阶段所需的软件和硬件要求,以及在VMware中配置和安装Windows 7系统的每一步操作。此外,我们还特别提到了如何在虚拟机上配置VMware Tools,以便更好地与宿主机进行交互。 通过本教程的学习,读者不仅能够掌握在VMware Workstation 17.0上安装Windows 7虚拟机的技能,还能了解到如何配置虚拟机的硬件以及安装VMwar

Python老吕的博客 2万+

Objective-C——消息、Category和Protocol

面向对象永远是个可以吐槽的话题,从开始提出到推崇备至,到充满质疑,一路走来让人唏嘘不已。面向对象的思想可谓历史悠久,20世纪70年代的Smalltalk可以说是面向对象语言的经典,直到今天我们依然将这门语言视为面向对象语言的基础。 面向对象是大部分编程语言的基本特性,像C++、Java、Objective-C这样的静态语言,Ruby、Python这样的动态语言都是面向对象的语言。但是如何编写面向

程序人生 1914

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

上一篇: 创建一个Mac OS X 下的Cocoa Application对话框 详解
下一篇: 关于Cocoa的窗口创建调用-一个nib包含两个窗口
小Mac
博客等级 码龄15年 6粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值