《JAVA编程思想》学习笔记一:面向对象思想(Object-oriented)

来源:互联网 发布:塞班软件下载s60v3 编辑:程序博客网 时间:2024/05/21 07:02

首先得声明下本笔记的落脚点和不足。这是JAVA编程思想学习笔记的第一篇,我也是抱着自己学习,惠及他人的意思搞的这个连载。由于鄙人水平实在有限,故难以挖掘很多概念的深层意思,可能只是说个大概吧。望看到的高手、大侠指点一二,共同进步当然是极好的。

书是昨天晚上看的,到了今天早上感觉似乎又忘得差不多了。足以见得,写个笔记是多么重要,起码把当下自己的认知水平记录下来了。说起面向对象思想,我在整个第一章没有看到具体的概念,查阅了互联网也没有发现权威的定义。说白了,这是一个无法直接归纳总结的一个概念。

维基百科:对象(Object)是类的实例。

递归解释“类”呢?

维基百科:类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。

必须再递归解释下“抽象”!

维基百科:抽象化(Abstraction)是指以缩减一个概念或是一个现象的资讯含量来将其广义化(Generalization)的过程,主要是为了只保存和一特定目的有关的资讯。

我用我的语言白话一下:对一件事物的归纳总结(即抽象的过程)形成类,然后给类实例化,故而产生了对象。实例化的过程接触计算机的都非常熟悉,new一下就出来一个对象,这当然不是面向对象的本质。面向对象思想的核心,鄙人认为应该是“抽象化”的过程。比如说,我们现在要构建一个购物平台,你自然而然地会想到建个商品库。我问你什么是商品,你说书是商品,手机是商品,这些物品都是啊。所以,当你表达出商品的时候,抽象化已经在你脑子里完成了。你把需要被标上定价对外销售的物品都抽象为商品了。

抽象商品这个概念或许容易,但把整个交易平台里的所有细节都抽象为类,这怕是不容易的。我们认识了对象这个概念以后,并不能立即解决所有问题,一个个对象是存在了,但是需要经过对象间的相互作用才能完成一系列的操作。比如说,笔在纸上画圈这样一个事物,可以形成笔和纸两个对象,然后经过画这个行为,产生了圈这样的结果。画是笔行为能力之一,所以对象不仅有属性(笔的长度,颜色),还有一些行为(画)。在笔画圈的过程中,还有一个很重要的细节容易被忽略,就是消息传递的过程。笔无法自己画一个圈,必须是人拿起笔,在纸上围绕一个圆心距离相等的地方连续画下去才产生了圈。我尝试使用伪代码来描述这个过程。

  1. class Pencil{
  2. float thickness;
  3. public draw(){
  4. }
  5. }
  6. class Canvas{
  7. Pencil p;
  8. public drawCircle(Point center,float radius){
  9. p.draw();
  10. }
  11. }

这段代码很明显的展示出了画布上画圆的过程。你会问,不是人拿着画的么?当然,可是从计算机编程的角度,人这个概念在解决画圆这个事情中,没有实质作用,所以会被抽象成画布自身的动作。这里面还存在一个问题,Pencil对象为什么会成为画布的一个属性呢?画布里有只铅笔?确实不容易理解。还是得从编程的角度来看,画布操作一直铅笔画了圆。就算是操纵也可以写成这样啊:

  1. class Canvas{
  2. public drawCircle(Point center,float radius){
  3. Pencil p = new Pencil();
  4. p.draw();
  5. }
  6. }

可是你会发现,当你需要改变一直铅笔的粗细的时候,就会变得很困难。所以定义成成员变量,是比较符合复用性的要求。你不需要在画不同粗细笔画时实例化N多只笔。这个例子中提及了两个概念,一个是消息的传递,一个是类的复用。类复用很多时候就是通过成员变量的形式来实现。这也是应该首先想到的方式。

面向对象还有三个很重要的特点,封装、继承、重载、多态。

封装(Encapsulation)

在书中的标题为“被隐藏的具体实现”。在大型开发项目中,合理分明的接口是模块间相互协同的重要保障,不同项目组开发的模块都不需要告诉对方具体的实现方式。只需要公布一套模块或者是类库的接口关系即可。Java中使用public,private,protected定义接口的开放程度。public表示紧随其后的元素对任何人都是可用的。private表示除类型的创建者和内部方法之外的任何人都不得使用。而protected与private作用相当,差别仅在继承的类可以访问protected成员。

继承(Inheritance)

维基百科:继承性(Inheritance)是指,在某种情况下,一个类会有“子类”。子类比原本的类(称为父类)要更加具体化,例如,“狗”这个类可能会有它的子类“牧羊犬”和“吉娃娃犬”。

继承就是对父类的复制,通过这种方式,我们不必再创建新的类型。通过继承得到的子类具备了父类的所有开放属性和开放接口。我们还可以通过在子类中添加新的方法来扩展子类的功能。

在继承中还涉及了一个非常重要的概念——重写(或称覆盖)。重写(override)即是对从父类继承的某个接口进行重新实现,以表现出不同的行为。就比如说犬科动物都会叫,但是狗是吠叫,而狼是嚎叫。狗在继承了犬科动物叫的行为时,对其进行了改造,而形成了吠叫。

重载(overload)

重载是在同一个类中,对同一个接口表现出不同的行为。通常重载都需要一些约定的规则,比如使用相同的方法名和不同的参数列表来实现。

多态(Polymorphism)

维基百科:多态(Polymorphism)是指由继承而产生的相关的不同的类,其对象对同一消息会做出不同的响应。

多态这个概念在很长一段时间我都很糊涂,如果光看概念似乎跟重写没多大差别。比如我们现在来模拟鸟类移动这样一个事物。

  1. class Bird{
  2. public move(){
  3. }
  4. }
  5. class Chicken extends Bird{
  6. public move(){
  7. }
  8. }
  9. class Duck extends Bird{
  10. public move(){
  11. }
  12. }

必然鸡和鸭子行走是不同的,如果现在需要建一个控制鸟类移动的控制器。

  1. class BirdController{
  2. public locate(){
  3. }
  4. }

这里怎么实现呢?难道在locate方法里判断传入的鸟的类型,然后实例化相应的鸟,再调用move方法?如果现在实现了100种鸟,是不是打算判断100种鸟的具体类型。这样的实现,代码恐怕难以维护了。那么请看下面的实现方式。

  1. class BirdController{
  2. public locate(Bird b){
  3. b.move();
  4. }
  5. }

这样实现,是不是优雅多了,我不管你是什么鸟,反正都具有move这个接口,只要可以接受同一类型消息的接口,这样调用永远正确。具体说来,b这个对象就代表了一只鸟,如果传入的是一只鸡,那么它就像鸡那样移动,如果传入鸭子,它就像鸭子那样移动。这个对象在不同的情况下表现出了多种行为,这种情况我们称之为多态。

在多态的概念中,还涉及到两个概念,即前期绑定和后期绑定。b.move()调用我们在编译时根本不知道是哪一段具体代码。只能是在执行时根据实际情况判断调用哪段代码。这样的情况我们称之为后期绑定,反之,如果在编译时可以确定其具体调用函数的代码时,我们称之为前期绑定。前期绑定多用在传统的面向过程的编程方式中。

另外,在谈到面向对象思想的时候,有必要说说接口(Interface)这一概念。接口就是一个类型事物开放用于接收外部消息的端口。比如说鸟类的移动,犬类的叫,是供外界调用传递消息的。但是Java接口通常只定义名称和参数列表,而不能对其进行实例化。

  1. Interface IMove{
  2. public move();
  3. }

这就是一个接口。我们来思考这样一个情况。多态要求调用的对象必须具有相同的接口。那么刚刚那个鸟类控制器我们可不可以这样实现呢?

  1. class BirdController{
  2. public locate(IMove i){
  3. i.move();
  4. }
  5. }

当然是可以的!只要是实现了IMove接口的对象,都可以进行调用。今天这一节只能写到这了。个人感觉很啰嗦,不简练,不准确。实在由于水平有限,能把问题说清楚,鄙人已经非常满足,实在不敢有更多的奢望。今天这一篇,我从早上一直写到了晚上,感觉对很多概念都是模棱两可的,根本了解的不透彻,必须查阅各种资料,以求获得一个更全面的认识。希望我的一点点小努力,能够对自己有帮助,也对各位有帮助吧。

原文链接地址:http://www.zz314.com/?p=364

0 0
原创粉丝点击