当单继承不够用,很难为问题域建模时,我们通常都会直接想到多继承。多继承是从多余一个直接基类派生类的能力,可以更加直接地为应用程序建模。但是Objective-C不支持多继承,由于消息机制名字查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题。不过其实 Objective-C 也无需支持多继承,我们可以找到如下几种间接实现多继承目的的方法:
消息转发
delegate和protocol
类别
消息转发
当向someObject发送某消息,但runtime system在当前类和父类中都找不到对应方法的实现时,runtime system并不会立即报错使程序崩溃,而是依次执行下列步骤:
分别简述一下流程:
1.动态方法解析:向当前类发送 resolveInstanceMethod: 信号,检查是否动态向该类添加了方法。(迷茫请搜索:@dynamic)
2.快速消息转发:检查该类是否实现了 forwardingTargetForSelector: 方法,若实现了则调用这个方法。若该方法返回值对象非nil或非self,则向该返回对象重新发送消息。
3.标准消息转发:runtime发送methodSignatureForSelector:消息获取Selector对应的方法签名。返回值非空则通过forwardInvocation:转发消息,返回值为空则向当前对象发送doesNotRecognizeSelector:消息,程序崩溃退出。
顾名思义,我们可以利用上述过程中的2、3两种方式来完成消息转发。
快速消息转发
快速消息转发的实现方法很简单,只需要重写 - (id)forwardingTargetForSelector:(SEL)aSelector 方法即可。
我来举个简单的例子,比如现有2个类:Teacher 和 Doctor,Doctor可以做手术(operate方法)。
- @interface Teacher : NSObject
- @end
- @interface Doctor : NSObject
- - (void)operate;
- @end
通过快速消息转发,可以很轻松的让teacher调用doctor的方法做手术。
Teacher类需要实现将消息转发给Doctor:
- - (id)forwardingTargetForSelector:(SEL)aSelector
- {
- Doctor *doctor = [[Doctor alloc]init];
- if ([doctor respondsToSelector:aSelector]) {
- return doctor;
- }
- return nil;
- }
虽然消息可以动态转发传递,但是编辑器的静态检查是绕不过的,那么问题来了,既然Teacher类没有实现operate方法又该如何声明呢?
到目前为止,我只想到下面2种方法:
声明方法1 ———— 类别
- @interface Teacher (DoctorMethod)
- - (void)operate;
- @end
声明方法2 ———— 导入头文件、调用时强转类型
Teacher类头文件需要包含Doctor头文件,告诉编译器去Doctor.h中可以找到operator方法的声明,并且在调用时强转类型。
- Teacher *teacher = [[Teacher alloc]init];
- [(Doctor *)teacher operate];
有兴趣可以思考一个问题:如果将其类型转成 id ,也可以编译通过,并实现转发。可是会带来什么隐患呢?
方法1使用类别足够清晰简便,为什么还要提出办法2呢 ? 我的想法是,方法1的弊端是抛出来的方法是定死的,而且在.h里露着;方法2就相对灵活,而且隐藏了我要转发的消息。
标准消息转发
标准消息转发需要重写 methodSignatureForSelector: 和 forwardInvocation: 两个方法即可。
发流程如图所示:
转发重写方法:
- - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
- {
- NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];
- if (signature==nil) {
- signature = [someObj methodSignatureForSelector:aSelector];
- }
- NSUInteger argCount = [signature numberOfArguments];
- for (NSInteger i=0 ; i<argCount ; i++) {
- }
- return signature;
- }
- - (void)forwardInvocation:(NSInvocation *)anInvocation
- {
- SEL seletor = [anInvocation selector];
- if ([someObj respondsToSelector:seletor]) {
- [anInvocation invokeWithTarget:someObj];
- }
- }
两种消息转发方式的比较
快速消息转发:简单、快速、但仅能转发给一个对象。
标准消息转发:稍复杂、较慢、但转发操作实现可控,可以实现多对象转发。
delegate和protocol
委托是Objective-C中最常用的一种回调机制。用法我觉得没什么好说的,总结一下该机制特点:
委托协助主体完成操作任务,将需要定制化的操作预留给委托对象来自定义实现,类似子类化主体。
除此之外,可以用作事件监听。
一时还真想不出来了…
类别
个人认为类别是Objective-C设计的一大精髓,也是我爱上Objective-C的最大理由。
类别是个强大的东西,它既可以为类添加方法,也可以添加实例。一定有不少人不认同,想提醒我:类别的局限性之一就是无法向类中添加新的实例变量。 背书真心毁人,听我举个例子慢慢说。
重新再来个Teacher类:
- @interface Teacher : NSObject
- {
- NSUInteger age;
- }
- @end
光有个年龄还不能满足对teacher的描述,我想加个profession实例来存teacher的专业。直观的想法是子类化Teacher,其实也可以用类别。
你需要了解一下 runtime 编程知识,关注一下 objc_setAssociatedObject 和 objc_getAssociatedObject 。
- //
- // Teacher+Profession.m
- //
- #import "Teacher+Profession.h"
- #import <objc/runtime.h>
- const char *ProfessionType = "NSString *";
- @implementation Teacher (Profession)
- -(void)setProf:(NSString*)prof
- {
- objc_setAssociatedObject(self, ProfessionType, prof, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- -(NSString *)prof
- {
- NSString *pro = objc_getAssociatedObject(self, ProfessionType);
- return pro;
- }
- @end
现在就可以通过setProf: 和 prof 来存取 teacher 的 profession 值了。
from:http://www.cocoachina.com/newbie/basic/2013/0528/6295.html
相关推荐
Objective-C是一种广泛用于苹果平台应用程序开发的编程语言,它是C语言的一个超集,并加入了Smalltalk风格的消息传递机制。本篇教程主要面向初学者,介绍了Objective-C的基础知识点和一些核心概念。 1. Objective-C...
"第六讲 多态性"讨论了多态在Objective-C中的实现,如方法重载和动态类型,这使得代码更具通用性和可扩展性。 "第七讲 分类与协议"讲解了分类的用途,它可以扩展已有类的功能,而协议则是Objective-C的接口定义,...
在这个场景中,我们关注的是Objective-C中的“继承”概念,这在创建类的层次结构中扮演着核心角色。继承允许一个类(子类或派生类)获取另一个类(父类或基类)的属性和方法,从而实现代码的重用和扩展。 标题中的...
1. **Objective-C基础**:Objective-C是在C语言基础上扩展的,因此,理解C语言的基本语法是必要的。Objective-C添加了消息传递机制、类和协议等面向对象特性。 2. **消息传递**:Objective-C中的对象通过发送消息来...
Objective-C是基于C语言的,主要用于构建iOS和macOS应用程序,而Objective-C++则是Objective-C的一个扩展,它引入了C++的特性,使得开发者可以同时利用Objective-C的动态特性和C++的面向对象编程能力。 ### ...
1. **Objective-C基础**:Objective-C是在C语言基础上扩展的,因此它包含了C的所有特性。书中会讲解基本的数据类型、控制结构、函数和指针等基础知识,同时介绍Objective-C特有的动态类型和消息传递机制。 2. **...
《Objective-C基础教程》是一本面向初学者的编程书籍,主要涵盖了Objective-C语言的基本概念、语法和编程实践,尤其适合那些想要踏入iOS应用开发领域的学习者。Objective-C是Apple公司开发的面向对象的编程语言,它...
Objective-C语法的基石是C语言的语法结构,这意味着所有的C语言代码都可以在Objective-C中直接使用。但是,Objective-C在C的基础上新增了消息传递机制,这是它与C语言的一个重要区别。在Objective-C中,方法调用是...
Objective-C是一种强大的面向对象编程语言,特别是在iOS和macOS...了解并熟练掌握Objective-C是成为苹果平台开发者的关键步骤,因为虽然Swift已经越来越流行,但Objective-C在很多现有的代码库和框架中仍然被广泛使用。
在Objective-C中,这些基础知识仍然适用,但Objective-C引入了面向对象的特性,如类、对象、继承、多态和消息传递。 1. 类与对象:Objective-C中的所有事物都是对象,它们由类定义。类是一个模板,描述了对象的属性...
Objective-C是C语言的超集,它扩展了C语言,加入了面向对象的特性。面向对象编程(OOP)的核心概念包括类、对象、继承、封装和多态。Objective-C通过消息传递机制实现了这些概念,使得代码更加模块化和可维护。 2....
Objective-C继承了C语言的基础语法结构,并在此基础上增加了面向对象的特性,包括类(Class)、对象(Object)、消息传递(Message Passing)等概念。具体特点如下: 1. **动态性**: Objective-C是一种动态类型的语言,这...
Objective-C是在C语言的基础上扩展了Smalltalk式的面向对象特性,使得它既有C语言的强大功能,又具备了面向对象编程的灵活性。 在Objective-C中,类是所有对象的基础。类定义了一组属性(实例变量)和方法(函数)...
Objective-C是一种面向对象的编程语言,它是C语言的扩展,最初由Brad Cox在20世纪80年代开发,并且广泛应用于Mac OS X和iOS的应用程序开发中。Objective-C在C语言的基础上增加了Smalltalk风格的消息传递机制,允许...
本书结合理论知识与示例程序,全面而系统地讲述Objective-C编程的相关内容,包括Objective-C在C的基础上引入的特性和Cocoa工具包的功能及其中的框架,以及继承、复合、源文件组织等众多重要的面向对象编程技术。...
**Objective-C**是一种结合了C语言的基础特性和Smalltalk式消息传递机制的面向对象编程语言。作为C语言的一个超集,Objective-C允许开发者直接使用C语言代码。此外,它还借鉴了C++的一些特性,尽管它并非C++的直接...
Objective-C 是苹果公司为其操作系统 macOS 和 iOS 开发的一种面向对象的编程语言。它在苹果的开发环境中占有核心地位,是创建 macOS 应用程序、iOS 应用程序以及 watchOS 和 tvOS 应用程序的基础。"Learn Objective...
- **继承、多型(Inheritance, Polymorphism)**:Objective-C支持类的继承,子类可以继承父类的属性和方法,多型允许对象以多种类型进行操作。 - **id 型别**:通用对象指针,可以指向任何Objective-C对象。 - *...
Objective-C运行时系统(Run time)是Objective-C语言的关键组成部分,它允许许多决策在编译时和链接时推迟到运行时进行。这意味着Objective-C不仅仅是依赖编译器,还需要一个运行时系统来执行编译后的代码。运行时...