面向对象的特性
面向对象具有四个基本特征:抽象,封装,继承和多态。
抽象
包括两个方面,一是过程抽象,二是数据抽象。过程抽象是指任何一个明确定义功能的操作都可被使用者看作单个的实体看待,尽管这个操作实际上可能由一系列更低级的操作来完成。数据抽象定义了数据类型和施加于该类型对象上的操作,并限定了对象的值只能通过使用这些操作修改和观察。抽象是一种思想,封装继承和多态是这种思想的实现。
封装
封装是把过程和数据包围起来(即函数和数据结构,函数是行为,数据结构是描述),有限制的对数据的访问。面向对象基于这个基本概念开始的(因为面向对象更注重的是类),即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。一旦定义了一个对象的特性,则有必要决定这些特性的可见性,封装保证了模块具有较好的独立性,使得程序维护修改较为容易。对应用程序的修改仅限于类的内部,因而可以将应用程序修改带来的影响减少到最低限度。但是封装会导致并行效率问题,因为执行部分和数据部分被绑定在一起,制约了并行程度。面向对象思想将函数和数据绑在一起,扩大了代码重用时的粒度。而且封装下的拆箱装箱过程中也会导致内存的浪费。
继承
继承是一种层次模型,允许和鼓励类的重用,并提供了一种明确表述共性的方法。新类继承了原始类的特性,新类称为原始类的派生类(子类和父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。继承性很好的解决了软件的可重用性问题。但是,不恰当地使用继承导致的最大的一个缺陷特征就是高耦合(即“牵一发而动全身”,是设计类时层次没分清导致的)。解决方案是用组合替代继承。将模块拆开,然后通过定义好的接口进行交互,一般来说可以选择Delegate模式来交互。使用继承其实是如何给一类对象划分层次的问题。在正确的继承方式中,父类应当扮演的是底层的角色,子类是上层的业务。父类只是给子类提供服务,并不涉及子类的业务逻辑;层级关系明显,功能划分清晰;父类的所有变化,都需要在子类中体现,此时耦合已经成为需求。
多态
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。很好的解决了应用程序函数同名问题,多态一般都要跟继承结合起来说,其本质是子类通过覆盖或重载父类的方法,来使得对同一类对象同一方法的调用产生不同的结果。覆盖是对接口方法的实现,继承中也可能会在子类覆盖父类中的方法。重载,是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样); 但继承会引入多态使用混乱的境况并产生耦合,更好的方法是使用接口。通过IOP将子类与可能被子类引入的不相关逻辑剥离开来,提高了子类的可重用性,降低了迁移时可能的耦合。接口规范了子类哪些必须实现,哪些可选实现。那些不在接口定义的方法列表里的父类方法,事实上就是不建议覆重的方法。如果引入多态之后导致对象角色不够单纯,那就不应当引入多态,如果引入多态之后依旧是单纯角色,那就可以引入多态;如果要覆重的方法是角色业务的其中一个组成部分,那么就最好不要用多态的方案,用IOP,因为在外界调用的时候其实并不需要通过多态来满足定制化的需求。