资讯专栏INFORMATION COLUMN

面向对象概念的学习和思考

jzman / 2319人阅读

摘要:摘要本文章关注点是理解面向对象概念,从抽象的角度上去理解对象,重点包括理解对象的作用,以及理解面向对象的三大特征封装,继承,多态。特性多态不同对象以自己的方式响应相同的消息的能力叫做多态。

摘要:本文章关注点是理解面向对象概念,从抽象的角度上去理解对象,重点包括理解对象的作用,以及理解面向对象的三大特征(封装,继承,多态)。本文重点关注的是理解概念。

在理解面向对象之前,首先回答几个问题
1. 什么是对象,类
类,即类型的意思,而每一个对象都是某类(类型)的具体实例;比如鸟和鱼,都是具体的对象,都是属于动物这个类;
对象最简单的描述就是:对象具有状态、行为、和标志;
具有状态异味着着对象可以拥有内部数据;
行为即方法;
标志即对象可以唯一的与其他对象区分开来,有些类似身份证的作业;

2. 为什么要面向对象以及对象的作用
在面向对象产生之前,最为熟知的是面向过程的编程,大学的入门课程C语言就是如此;
“面向过程(结构化编程)是以功能为目标导向来设计构造应用系统,这种做法导致我们设计程序时,不得不将客体所构成的现实世界映射到由功能模块组成的解空间中,这种转换过程,背离了人们观察和解决问题的基本思路。
可见结构化设计在设计系统的时候,无法解决重用、维护、扩展的问题,而且会导致逻辑过于复杂,代码晦涩难懂。于是人们就想,能不能让计算机直接模拟现实的环境,用人类解决问题的思路,习惯,步骤来设计相应的应用程序?这样的程序,人们在读它的时候,会更容易理解,也不需要再把现实世界和程序世界之间来回做转换。
与此同时,人们发现,在现实世界中存在的客体是问题域中的主角,所谓客体是指客观存在的对象实体和主观抽象的概念,这种客体具有属性和行为,而客体是稳定的,行为不稳定的,同时客体之间具有各种联系,因此面向客体编程,比面向行为编程,系统会更稳定,在面对频繁的需求更改时,改变的往往是行为,而客体一般不需要改变,所以我们就把行为封装起来,这样改变时候只需要改变行为即可,主架构则保持了稳定。 ”[1]

那抽象出的对象的角色是什么呢?
对象可以理解为模拟中我们概念中的客体,因此对象的存在的目的就是为提供服务,服务链结构可以多样化。比如汽车为司机服务,而零件商家为汽车服务(提供汽车零件)。
"将对象看做是服务提供者有一个好处就是有助于提高对象的内聚性。"[2]

3. 面向对象三大特性
面向对象的三大特性的是理解面向对象的关键点。
特性1: 封装性
首先要问为什么要封装以及封装什么?
封装的的原因在于:封装可以让使用者看不到具体的实现细节,创建者可以不用担心被使用者误改,从而减少程序Bug;
而且,允许库设计工作者可以改变程序内部结构而不担心影响客户端。创建者改动需要调用者改动代码的现象特别是以前很常见的。
同时,客户端的目标也更明确:客户端程序员不关心具体的实现,只关心拿创建者的接口的功能是什么。

封装的内容包括三个方面:
(1)把自己的数据和方法只让可信的类或者对象操作,即隐藏或者暴漏数据、接口。
(2)"找到变化并且把它封装起来,你就可以在不影响其它部分的情况下修改或扩展被封装的变化部分,这是所有设计模式的基础,就是封装变化,因此封装的作用,就解决了程序的可扩展性"[1]
(3)现实写代码过程中,更多接触的是:找到重复度高的,对代码可重用的部分进行封装;

特性2: 继承
面向对象编程(OOP)一个主要功能就是“继承”。继承它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下可以复用基类的方法或者对这些功能进行扩展。
在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Cat,Dog,因此这两个类都可以继承 Animal 类。否则,没有这种关系的就不要继承了。

接下来,理解下is-a和is-like-a关系

对于继承有这么一个争论:继承应当只覆盖基类(并且不添加基类中没有的新成员函数)吗?这就意味着派生类与基类是完全相同的类型,因为它们有相同的接口。结果是,我们可以用派生类的对象代替基类的对象。这被认为是纯粹替代(pure substitution),常常被称做替代原则(substitution principle)。在某种意义上,这是对待继承的理想方法。我们常把基类和派生类之间的关系看做是一个“is-a(是)”关系,因为我们可以说“圆形是一个形体”。对继承的一种测试方法就是看我们是否可以说这些类有“is-a”关系,而且还有意义。

但是,有时需要向一个派生类型添加新的接口元素,这样就扩展了接口。这个新类型和基类不完全相同了,而且这些新接口元素不能从基类访问。这可以描述为“is-like-a(像)”关系;新类型有老类型的接口,但还包含其他函数,所以不能说它们完全相同[3]。

同时,继承虽然可以复用基类的方法/属性,但是很多时候的滥用导致的问题太多,比如覆盖基类后,子类默认覆盖相同名字的父类方法。继承是中非必要的话就不需要覆盖了,是一定必要的时候明确指出来,Kotlin语言中继承基类后,要明确指出覆盖的方法。

继承的缺点[4]:
a.破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
b.支持扩展,但是往往以增加系统结构的复杂度为代价
...

继承使用原则:

A.继承树的层次不可太多,尽量保持在2-3层,首先过多的继承会导致对象模型的机构太复杂,难以理解,增加了开发和设计的难度,如果子类和父类之间还有频繁的方法和属性覆盖,更增加了多态机制的难度。其次影响系统的可扩展性,继承树的层次越多在继承树上增加一个新的继承分支就需要创建更多的类。

B.使用继承树上的类时应该尽可能把引用变量声明为继承树的上层类型,首先上层类型定义了下层子类都拥有的属性和方法并且尽可能为多数方法提供默认实现从而提高代码的可重用性。其次上层类型代表一种服务接口描述系统所能提供的服务,父类不一定实现这个服务,提高系统的松耦合及系统本身的可维护性。

JAVA为什么是单继承结构?
在单继承中,所有对象都具有一个共同的接口,所以他们归根到底属于同一基本类型。而多继承(C++)是无法保证所有对象都属于同一基本类型。对象的创建和参数的传递相对来说变得简单,而且使得垃圾回收器的实现变得容易很多,由于所有对象有其类型的基本信息,因此不会出现无法确认对象类型而陷入僵局[5](通俗理解就是我系统运行后,不知道哪个类型的对象在work)。

特性3:多态

不同对象以自己的方式响应相同的消息的能力叫做多态。多态性(polymorphisn)允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
与多态相关的具体是覆盖,重载。
覆盖,是指子类重写父类的函数。
重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

区分前期绑定和后期绑定
前期绑定,在程序执行前根据编译时类型绑定,调用开销较小,如C语言只有前期绑定这种方法调用。
后期绑定,是指在运行时根据对象的类型进行绑定,又叫动态绑定或运行时绑定。实现后期绑定,需要某种机制支持,以便在运行时能判断对象的类型,调用开销比前期绑定大。
Java中的static方法和final方法(private属于final方法,详细的解释见《Java编程思想》)属于前期绑定,子类无法重写final方法,成员变量(包括静态及非静态)也属于前期绑定。除了static方法和final方法(private属于final方法)之外的其他方法属于后期绑定,运行时能判断对象的类型进行绑定[6,7].

4. 对象之间的交流

那么为了能让对象之间有交互行为,能相互发送消息和接受消息,该如何做呢?一般来说有两种方法:1)方法调用,A对象调用B对象的方法,这种方法最常用最直接,但是缺点是会导致A依赖于B。这个问题我们往往会通过面向接口编程在一定程度上消除这种依赖关系;2)事件消息模式,生产者-消费者模式,即采用触发事件响应事件的模式;通过这种方式,A对象就不是直接调用B对象的方法了,而是触发一个事件,然后B对象去响应这个事件,或者如果采用消息总线的方式的话,就是A对象通知消息总线发布某个事件,然后消息总线发布这个事件,然后B对象响应这个事件[8].

参考资料
[1]博客: http://www.cnblogs.com/seesea...
[2]书籍: think in java (4 edition), page 1-4
[3]博客:http://book.51cto.com/art/201...
[4]博客:http://www.cnblogs.com/nuaalf...
[5]书籍: think in java (4 edition), page 11
[6]博客:http://www.cnblogs.com/NotOnl...
[7]博客:http://droidyue.com/blog/2014...
[8]博客:http://www.cnblogs.com/netfoc...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66041.html

相关文章

  • 什么是面向对象

    摘要:第一章面向对象小白是一门完全面向对象的编程语言嗯什么是面向过程什么又是面向对象呢大佬在我们正式进入学习这部分前,了解一下面向过程和面向对象这两个概念,对于我们接下来的学习有很大的好处。这一部分我们会在面向对象学习结束后进行系统的整理和总结。 showImg(https://segmentfault.com/img/remote/1460000019303357); 第一章 面向对象 小...

    DirtyMind 评论0 收藏0
  • java 面向对象程序设计入门

    摘要:一学习资料今天入门了一门新的编程语言,主要对照清华大学出版社教材语言与面向对象程序设计,附带在上写了一个实例。重要的概念,如对象,属性,方法等。因此需要在实操中强化操作技能,加深对概念的巩固。辅以灵活引用已有的代码库,加速以及项目的进展。 一、学习资料:今天入门了一门新的编程语言,主要对照清华大学出版社教材《Java 语言与面向对象程序设计》,附带在eclipse 上写了一个实例。 二...

    Profeel 评论0 收藏0
  • 理解JavaScript核心知识点:原型

    摘要:首先,需要来理清一些基础的计算机编程概念编程哲学与设计模式计算机编程理念源自于对现实抽象的哲学思考,面向对象编程是其一种思维方式,与它并驾齐驱的是另外两种思路过程式和函数式编程。 JavaScript 中的原型机制一直以来都被众多开发者(包括本人)低估甚至忽视了,这是因为绝大多数人没有想要深刻理解这个机制的内涵,以及越来越多的开发者缺乏计算机编程相关的基础知识。对于这样的开发者来说 J...

    iKcamp 评论0 收藏0
  • 一道面试题引发思考

    摘要:下面我们来使用面向对象类图这里就不再画了首先面试题中所提到的我们都可以看成类,比如停车场是一个类吧,它里面的车位是一个类吧,摄像头,屏幕。。。 以下是某场的一道面试题(大概): 1、一个停车场,车辆入场时,摄像头记录下车辆信息2、屏幕上显示所接收的车辆的信息情况(车牌号)以及各层车位的车位余量3、停车场一共四层车位,其中的三层都为普通车位,还有一层为特殊车位(体现在停车计费价格上面的不...

    Apollo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<