OOP(面向对象程序设计)是一个简单又复杂的课题,之所以简单是因为其概念清晰,内容简单,之所以复杂是因为没有固定的模式可寻,正所谓千人千面。
从本节开始,笔者大概会用5篇左右不同的专题来讲解OOP程序设计,OOP是一种设计思想非OjbectiveC专属,学习OOP编程核心是掌握其思想,然后寻找OOP在不同编程语言中的实现方式。
OOP基本概念
先来看下OOP编程的几个重要概念,下图是笔者自己总结的,可能并不符合多数课本上的描述,非笔者要另起炉罩,只不过不想千篇一律,从另一个角度来理解下OOP。
OOP设计
接口和类
注:在ObjectiveC中的接口实现为协议(protoful),此处我们沿用多数语言的术语还是称为接口。
- 接口:声明,只声明作用但不做实现,类似于抽象,在接口中只说明了能做什么事,但具体怎么做并不负责;其作用也可以理解为代理;
- 类:也称为实现,实现接口中声明的事的具体做法。比如我能生产汽车(接口),但具体怎么生产买家就不需要关心了,我可以建厂生产,也可以找代理,可以放在亚洲生产,也可以放在非洲生产。这种分离的模式会给程序设计带来最大的灵活性,比如更高给的RPC和分布式全是围绕分享思想来设计的。
继承关系
从上面可以看出OOP中的关键元素只有两个,所有OOP的设计全是围绕声明和实现相分离的思想来实现的。继承是OOP中比较核心的一个概念,类比下现实的例子,比如电商的类目,类目鞋可分为男鞋、女鞋。
上图中有两点需要说明:
- 二级关系一般表示 is a的关系;
- 多级关系一般除了表示is a的关系后,最重要的是功能实现的抽象;
- 类和接口都可以有继承关系,在多数语言中只允许单继承,即is A,就不能是is B;
混合模式
上面我们只是讲了声明和实现的简单关系,在实际编码过程中遇到复杂情况时一般会表现为以下关系,在真实编写代码时只有两种对OOP的使用模式:不用或是混合模式使用,所谓的简单使用多数用于数据模型的抽象上(数据对象的属性设计,无属性操作的实现)。
抽象类
抽象是一个比较复杂的概念,上述的设计模式是严格区分声明和实现的,在某种程度上有些死板,有没有一种中间状态来综合一下呢,答案就是抽象类,着重理解下设计的改变。
有几点需要注意:
- 抽象类由声明+实现两部分组成;
- 抽象类本质上它是一个类,不具备接口的多继承特性。
OOP的问题
业务和抽象
OOP的最大问题就是如何来设计,还是看上面我们举的电商的类目的例子,鞋可以分为女鞋和男鞋,如果再加一个童鞋的话,那么类目要如何设计呢?
童鞋划分到鞋和童装貌似都合理,但这打破了OOP设计的思想,在现实过程中会给运营和成本合算带来巨大的问题。因为职责不单一,即双头领导,双头汇报。这个问题的解决没有统一的解决方案,读者可以思考下?
业务和组合
OOP还有一种设计思想,组合,这个就是字面意思,但其设计起来也会有很多问题存在,比如下面两种设计模式。
上面的三种组合设计从OOP角度来看没有好坏之分,我们只能从现实的角度来评价,看下下面几种简单的业务场景:
- 车厂自己生产所有部件,且不关心轮毂和轮胎,也不关心其数据收集,那么方案1比较合适;
- 车厂的轮毂和轮胎由不同供应商提供,车厂要时刻关注其数据情况,那么方案2比较合适;
- 车厂的车轮为标准采购,由供应商管理轮毂和轮胎,车厂只关心标准定义的车轮,那么方案3会比较合适。
OOP的核心
好了,最后总结一下OOP的核心,笔者认为OOP的实现只是一个表面的事情,重在形。其真正的核心并不是编程技巧,而是对实际业务的理解能力,所以掌握OOP的核心笔者认为一定要遵循以下思想:
重点在于:
- 设计或抽象要符合实现业务场景;
- 程序实现的目标并不是业务的功能堆砌实现,而是业务场景的还原;
OjbectiveC中的OOP概念
通用的OOP术语
- 类:class,有时也称对象object,是一种表示对象类型的结构体,包含变量、构造函数、方法,通常采用骆峰式命名方法;
- 实例:instance,是类的一种具象表式,一个类可以有多个实例,每个实例占有不同的内存地址;
- 消息:message,一般也称为方法method,指对象可以执行的操作;
ObjetiveC中的术语
以下是ObjectiveC的特殊概念,在ObjectiveC语言中会成对出现,采用同名的方式自动绑定。
- 接口:interface,类的特征描述;
- 实现:implementation,使接口可正常工作的代码;
- 协议:protoful,类功能的补充;
在Objec中,接口和实现是一个固定的组合,这是ObjC语言的一个标准。
命名空间
在ObjC中没有类似java那样的package概念,Objc中的命名空间实际上是由类的前缀来定义的,比如NS表示官方Foundation库对象,CF表示Foundation中最早实现的一批API的命名空间。在真正开发代码时,建议以公司名称的首字母缩写做为所有的类的前缀以此来区分不同的命名空间,或是以模块功能缩写来区分不同的命名空间,比如
//系统api
NSString
//公司缩写
ZZUser
//功能模块,角色注册
ZZRORegister
关于NSObject
和java一样,ObjC的OOP设计过程中,所有的对象也会有一个基类,名为NSObject,它有一些比较有用的方法,常用的如下:
-
-(BOOL) isKindOfClass: class-object:对象是不是class-object 或其子类的成员
-
-(BOOL) isMemberOfClass: class-object:对象是不是class-object的成员
-
-(BOOL) respondsToSelector: Selector:对象是否能够响应selector所指定的方法
-
+(BOOL) isSubclassOfClass: class-object:对象是否是指定类的子类
-
+(BOOL) instancesRespondToSelector: Selector:指定的类实例是否能响应selector
-
-(id) performSelector: selector:应用selector指定的方法
-
-(id) performSelector: selector withObject: object:应用selector指定的方法,传递参数object
-
-(id) performSelector: selector withObject: objectl:withObject: object2:应用selector指定的方法,传递参数objectl和object2
//类实例是否相同
if ([obj1 class] == [obj2 class])
if ( [Square respondsToSelector: @selector (alloc)] == YES )
//类是否包含某个成员, myObj1是一个变量实例, Fraction是一个类
if( [myObj1 isMemberOfClass:[Fraction class] ] )
//指定一个回调方法,一般用于委托
[Fraction instancesRespondToSelector: @selector (setTo:over:)]
- (void) setTo: (int)i over:(int)j{
}
SEL action = @selector(draw:);
- (void) draw{
}
本节内容先了解到这里,这是笔者特意设计的,读者可以先从上述知识上试着自己来实现,后面再详细介绍ObjectiveC中的实现,带着自己的实现来学习ObjC的标准实现可能掌握的会更牢靠,因为OOP就是一学就会,一用就废的东西。