对象是一个自包含的实体,用一组可识别的特性和行为来标识。

  本人对于可识别特性的认知是就是类的属性。就像是一个“人”的类,那么它作为一个类就需要有些属性,让我们了解它为什么是“人”。每个人出生的时候都会有一个特别的标识,就是身份证ID,那么它就是属于“人”的可识别特性。

  而行为就是方法了,通俗的将就是动作。还是那个问题,“人”会有什么动作呢?比方说吃饭(eat),睡觉(sleep)等等。所有“人”可以做的动作都可以写到方法之中,而写代码时候,也许我们并不需要这么多动作,就可以按照需求来选择。

  所以用一段学术一点的讲法就是说:类就是具有相同的属性和功能的对象的抽象的集合。

  这个时候大家可能对于类已经有一个基本的了解了,在java中,“类”是java的四大特性中两种特性的体现:封装和抽象。这个时候读者们可能会有疑问,什么是封装和抽象呢?

  先来聊聊“封装”吧。上度娘大家输入“封装”,在百度百科中有对封装的详细解释,当然我们只需看程序部分的。

  封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。(引自百度百科)

  看起来是不很深奥?那么就可以跳过上段直接从头开始看,告诉你,只要你已经了解了前三段,那么你就已经摸到封装的门槛。其实就是把“人”的特性和“人”的动作(即属性和方法)放在一个类中,那么这种写代码的行为就是封装了。封装有很多好处,第一:良好的封装能够减少耦合;第二:类内部的实现可以自由地修改;第三:类具有清晰的对外接口。

  并且你还同步了解了什么是抽象了呢,知道么?把一个实实在在的东西从现实中提取出来,放到代码中的行为就是抽象了。之后要写的“人”的类那就不是真的在现实中存在的,而是我们把它提取出来,让他在代码世界中存在了呢。这么一想,是不是有一种自己是造物主的感觉呢,是不是还有点小激动呢?

  动手一起来写一个“人”的类吧。

 

 

图 1

 

  Ok,Now let's take a look at this picture parsing.

 

图 2

 

  也许读者会有一个疑问,为什么要把ID属性的修饰符设置为private,而不是public,直接设置为public是可以做到对变量的既读有些。是的,只是修改ID,那么把ID的属性设置为public也是可以的,但是作为一个“人”,是有隐私的,我们其实并不希望其他“人”能够直接知道自己的身份证号,而是当他询问的时候,再告诉他,将修饰符设置为public就好像,你直接把身份证号贴在自己的身上然后再大路上走,而改为private,那么身份证号就只有自己知道了,只有别人问你(即访问get方法)时,你才告诉他自己的身份证号。而这个属性只有get方法,表示这个属性是只读的,其他人没有办法来修改这个属性。

  创建了类之后,我们该如何访问这个类呢?

  有基础的人一定想到了,对的,就是将类实例化。实例化,就是创建对象的过程,使用new关键字来创建的。来看看代码吧。

 

图 3

 

图4

 

  有人会问在(图 1)的时候,并没有写过构造方法,那么那个时候People类有构造方法么?当然是有的,如果不在类中写构造方法,那么系统就会默认生成一个空的构造方法,但如果你有写过构造方法,那么这个空的构造方法就会消失了。

  将时间推到(图 1),这个时候,笔者并没有写构造方法,那么怎么对People类进行实例化呢?很简单,只要这样写就好了:People people = new People();

  大家想到了么?

  现在我们,为这个People类,多增加一个属性name。先不要看代码,来试试看。

 

图 5

 

  接下来,笔者来讲讲继承。

  先来创造两个类,分别是学生(Student)和老师(Teacher)。

  学生类:属性:ID,name,answer(答案);方法:eat(),exam(int a,int b);

  老师类:属性:ID,name;方法:eat(),correct(int answer);

 

图 6

 

  仔细比较代码,有没有觉得这个代码中有很多重复的代码呢?那么我们就得思考,如何将这些代码拿出,可以使这个代码看起来更简单整洁。

  其实,老师和学生,如果不管他们的身份,那么他们其实有个共通,就是他们都是“人”。由于老师和学生都是人,就同样拥有身份证号属性和姓名属性,并且都拥有吃饭的的行为,所以老师和学生与人之间是继承关系。

  对象的继承代表了一种“is a”的关系,如果两个对象A和B,可以描述为“B”是“A”。老师是人,就说明了老师和人之间是继承和被继承的关系,实际上,继承者还可以理解为是对被继承者的特殊化,因为它除了具备被继承者的特性之外,还具备之间独有的个性。比如学生有一个“exam(考试)”的方法,而老师没有,老师有一个“correct(批改)”的方法,而学生没有。继承定义了类如何相互关联,共享特性。继承的工作方式是,定义父类(基类)和子类(派生类),其中子类继承父类的所有特性。子类不但继承了父类的所有特性,还可以定义新的特性。按照之前的例子,并不是所有的人都有考试的方法和改卷的方法的,因此在人的子类学生或老师中,就要突出这种特性,写上这些方法。

  Let’s to try.

 

图 7

 

图 8

 

  对比现在和之前的代码,是不是简洁了很多呢?这就是继承的优点。不用继承的话,如果要修改功能,就必须在所有重复的方法中修改,代码越多,出错的可能性就越大,而继承的优点是,继承使得所有子类公共的部分都放在了父类,使得代码得到了共享,这样就避免的重复,另外,继承可使得修改或扩展继承而来的实现都较为容易。

  但是继承也是有缺点的,就是活如果父类变的话,那么子类就不能不变了,如果让学生去继承老师,那么就乱套了。另外,继承为破坏包装,把父类实现细节暴露给子类,这其实是增大了两个类之间的耦合性的。继承是一种类与类之间强耦合的关系。不过,当两个类之间具备“is a”关系时,就可以考虑用继承了。

  学好继承最好是记住三句话:如果子类继承于父类,第一、子类拥有父类非private的属性和功能;第二、子类具有自己的属性和功能,即子类可以扩展父类没有的属性和功能;第三、子类还可以以自己的方式实现父类的功能(方法重写)。

  对于方法重写,笔者现在来举个例子。

  对于学生来说,吃饭是要到学生食堂吃的,而对于老师来说,吃饭就是要到职工食堂吃了。可是如果调用学生或者老师的eat方法时,只能在控制台输出I’m eating.如果要实现以上的两种情况,那么这个时候就要使用方法的重写了。

图 9

 

图 10

 

  最后,来聊聊java中面向对象的最后一个特性:多态。

  多态表示不同的对象可以执行相同的动作,但是要通过他们自己的实现代码来执行。打个比方吧,学校经费不足了,所以要关闭一个食堂,把大家都叫到一个食堂去吃饭,这个时候只要是“人”就都可以去食堂吃饭了,而这个食堂是不检验进入食堂的人的身份的,只要是人就能进去了。

  这里要注意几点:第一、子类是以父类的身份出现的;第二、子类在工作时以自己的方式来实现;第三、子类以父类的身份出现时,子类特有的属性和方法就不可以使用。这样说来其实方法的重写就是一种多态的体现形式了。不同的对象可以执行相同的动作,但是要通过它们自己的实现代码来执行。

 

图 11

 

  到这里为止,面向对象的四大特性就都介绍完了,希望以上的文章对大家有所帮助,最后谢谢《大话设计模式》给了全面复习面向对象的四大特性的机会,并且给予我写这篇文章的理论基础。

 

  部分段落摘自《大话设计模式》