《疯狂Java讲义》第2章——理解面向对象

      在本章中,作者主要从以下两个方面进行展开,第一个是简要介绍面向对象,第二个是简要介绍UML,本章结构如下所示:

  • 面向对象
    • 结构化程序设计简介
    • 程序的三种基本结构
    • 面向对象程序设计简介
    • 面向对象的基本特征
  • UML
    • UML概述
    • UML图分类

      然而本章并不打算介绍UML,因为本人认为,UML图等到碰到的时候,再回来看一看具体的定义,未尝会比在这里先全部讲一遍,效果来的差。

      因此,本篇文章只叙述第一部分——面向对象:

            1、结构化程序设计简介:

                 1)设计原则:

                           结构化程序设计主张按功能分析系统需求,遵循“自顶向下、逐步求精、模块化”的设计原则。

                 2)程序结构:

                           结构化程序设计的最小单元是函数,每个函数接收一些输入数据,然后对这些数据在内部进行处理,结束后输出处理结果,从而完成特定的小功能。作为程序入口的函数称为主函数,其他函数由主函数直接或间接地调用,多个函数通过调用关系组成模块,而多个模块最终组成系统。

                 3)自身局限:

                           a)设计不够直观:与人类思维习惯不一致,需求分析时需要将现实世界的事物细化到具体的功能

                          例如:对于现实世界的“洗衣机”,运用结构化程序设计,需要将洗衣机分解为“注水”、“漂洗”、“脱水”等基本功能,而人们的思维只是单纯的“洗衣机能帮我洗衣服”,不会去关注到每个功能——“注水”能帮我干什么,“漂洗”能帮我干什么……等等

                           b)可扩展性不强:结构化程序设计采用“自顶向下”的设计方式,当用户需求改变时,需要自顶向下修改模块结构,维护成本比较高

            2、程序的三种基本结构:

                 1)顺序结构:表示程序中的操作按照它们在源代码中的排列顺序依次执行,看图:

Created with Raphaël 2.1.0 开始 操作1 操作2 结束

                   在上图中,从上到下是源代码再程序中的排列顺序,先执行操作1,再执行操作2,这就是顺序结构

                 2)选择结构:也称为分支结构,表示程序的处理需要根据某个特定条件,选择其中一个分支执行,选择结构可分为以下几种子类型:

                                 a)双选择结构:

Created with Raphaël 2.1.0 开始 条件成立? 操作1 结束 操作2 yes no

                   在双选择结构中,无论条件成立与否,都必须选择操作1和操作2中的其中一个来执行

                                 b)单选择结构:

Created with Raphaël 2.1.0 开始 条件成立? 操作1 结束 yes no

                   单选择结构是双选择结构的特例——当双选择结构中的操作1或者操作2其中之一为空操作时,双选择结构即成为单选择结构

                                 c)多选择结构:

Created with Raphaël 2.1.0 开始 条件1成立? 操作1 结束 条件2成立? 操作2 条件3成立? 操作3 yes no yes no yes no

                   多选择结构实际上是双选择结构的延伸——当双选择结构中的操作2又是一个双选择结构时,即演变出多选择结构。

                 3)循环结构:表示程序反复执行某一结构,直到某个条件不成立时停止执行,循环结构可分为两种类型,看图:

                                 a)当型结构:

Created with Raphaël 2.1.0 开始 条件成立? 操作1 结束 yes no

                   当型循环结构中,当条件成立时,执行循环,否则结束循环(此图有些怪异,因本人初次使用markdown语言绘制流程图,比较不熟悉,暂时没想到把此图画得好看的办法)

                                 b)直到型结构:

Created with Raphaël 2.1.0 开始 操作1 条件不成立? 结束 yes no

                   直到型循环结构中,先执行操作1,再进行判断,如果条件不成立,则继续执行循环,否则结束循环。

            3、面向对象设计程序设计简介:

                 1)基本思想:

                           从现实世界客观事物出发,充分运用人类的自然思维方式,强调以现实世界中的事物作为中心来分析与设计,把这些事物为,作为软件系统的基本组成单元。

                           例如,现在考虑洗衣服这个需求。

                           在过程化程序设计中,注水、漂洗、脱水等功能是必须要首先考虑的东西,也就是说——我现在要实现注水、漂洗、脱水这些功能,然后才能有一个洗衣机,然后才能洗衣服。

                           而在面向对象程序设计中,这些功能被封装到了洗衣机类当中,考虑问题的直接对象是洗衣机,而不是这些功能,也就是说——我现在要一台洗衣机,这台洗衣机有注水、漂洗、脱水这些功能,然后我就可以洗衣服啦!

                 2)类的组成:

                           a)成员变量:用来描述类的状态,例如,人作为一个类,人的身高、体重,都是人的状态,所以都可以抽象为人类的成员变量

                           b)方法:用来描述类的行为,例如,人作为一个类,人吃饭、人跑步,都是人的行为,所以都可以抽象成人类的方法

                           c)成员变量与方法的关系:方法可以改变成员变量的数据,例如,人作为一个类,通过跑步这个方法,可以改变身高、体重这些成员变量的数据值。成员变量和方法之间存在以下等式:

                                成员变量(状态数据)+方法(行为)=类定义

            4、面向对象的基本特征:

                1)封装:封装是将类的内部状态数据隐藏起来,同时向外提供按一定规则暴露这些数据的方法的一种手段。

                这里的按一定规则,是本人对于封装的理解——封装不可能是将所有数据隐藏起来,然后又用方法将所有数据开放出去,因为这样子做是没有意义的——就像你自己家里有很多价值连城的珍宝,你把它们都放在上锁的保险箱里面,但又把保险箱的钥匙放在旁边,并且把家门打开,你会这么傻么?不会,你肯定是把钥匙带在自己身上,别人要获得你的珍宝,必须拿出一定的交换物,你才会将自己的珍宝给他。因此,在封装这个概念中,方法对于类内部状态数据的开放,肯定不是完全开放,而是有条件的开放,在满足一定条件的情况下,外界才能获得类内部的数据

                2)继承:继承是软件复用的一种手段,当子类继承父类之后,子类将获得父类允许继承的状态和方法。

                相对于允许继承,就有一个不允许继承,那么允不允许继承,其实是由父类内部成员变量以及方法前的访问修饰符(后续将会讲到)控制的。那么既然要实现软件复用,为什么不允许子类完全继承父类的数据呢?这里不做深一步的讨论,还是举个日常生活中的例子:父亲的财产,正常来说是由儿子来继承的,假如这个父亲比较迷信,希望有些东西能常伴自己于地下,于是就把这些东西藏起来,不给儿子继承,那儿子自然就得不到那份属于父亲的私密财产了。这个比喻可能不太确切,但可以说明一点——面向对象中的继承,并不是全盘继承,还要看父类允不允许子类来继承。

                3)多态:书中的解释是——多态指的是子类对象可以直接赋给父类变量,但运行时依然表现出子类行为特征

                我以前在面试的时候,被问到多态,总是只有一句话“在语法层面看,多态是子类的实例可以赋给父类的变量……”,然后后面就不知道怎么说了,按照本书的说法,我只说了一半,而且并未说到点上。

                其实,多态其实也可以称为“后期绑定”。那么,什么叫后期?绑定什么?其实后期就是运行期,而绑定的对象就是实际new出来的对象,也就是说,对象的引用,是在运行期的时候才去绑定具体new出来的对象。既然后期是运行期,那么前期肯定就是编译期,而后期进行了绑定,那前期肯定是未绑定状态,也就是说,编译期的时候,对象的引用并不知道指向的是具体哪个对象。

                因为继承允许我们将子类类型当成父类类型,所以我们可以将编译期那个“迷茫的”对象引用定义成父类类型,只要保证它在运行期绑定的具体对象类型是该父类的子类对象,就不会出错。因此,调用方法的时候,在运行期之前,其实并不知道调用的是哪个子类的方法,只有到了运行期,进行具体子类对象的绑定后,JVM才能确定执行哪个方法,而这就是书中解释的后半部分——“运行期依然表现出子类的行为特征”的原因。

                4)消息:面向对象世界中,对象之间必定是要进行交流和协作的,那么就需要一个机制来实现,这就是消息,消息是一个实例与另一个实例进行通信的一个机制。

                对于封装、继承、多态,消息,本书第五章——《面向对象(上)》,以及第六章《面向对象(下)》将会有更加详细的讨论,此处不再展开。

你可能感兴趣的:(JavaSE)