也说面向对象编程

       说起面向对象编程,每个人都有自己不同的理解也能说出来一二,下面说说经历工作后我对面向对象编程的理解。
  一、面向对象的前身
      面向对象的设计方法在20世纪60年代后期,诞生于于simula的编程语言中最早开始使用的。它是作为一种模拟语言,对于模拟的物体引入了对象的概念。比如说交通系统的模拟,车和信号就变成了对象,一辆车和一个信号就是一个一个的对象,而用来定义这些车和信号的就是类。从20世纪70年代到80年代又经历过smalltalk编程语言系列的发展对面向
对象编程影响很大,之后的C++也是受到了它的影响,在之后的java、C#在前面语言的基础上发展成符合面向对象特点的编程语言。由于早期的计算性能原因,面向对象并没有火起来,随着计算机性能的提高,对灵活性、可扩展性、可维护性、适应快速需求变更的面向对象编程才开始兴起来。
  二、面向对象的思想
    面向对象是把现实世界中具体的事物看作对象,抽象出来物体的侧面,把共通的特性进行抽象化,可以说面向对象是对现实世界中具体事物的反映。有三个特征:继承、封装、多态。
     软件开发最大的困难就是复杂性,我们知道人类的大脑无法做太复杂的处理,记忆力和理解力也是有限的,而计算机却没有限制,它可以处理海量数据、复杂的运算而且执行效率比人高。但是随着越来越多的数据需要计算机的处理,对软件的要求也越来越高,复杂性也越来越大。这样就面临着两个问题,计算机的性能再高但还是有限的,人类可以理解的复杂度。为构建大规模的软件人们提出了一下几种方法:
  1、结构化编程
    主要是把程序的执行顺序限制为顺序、分支、循环三种。把共通的处理归结为例程,这样程序就变得可控制,所有的执行语句变成如下形式:命令1->命令2...;满足条件a执行操作,否则执行另一操作;循环,满足条件一直执行代码段否则跳转执行下一代码段,条件不成立跳出。结构化编程有效降低了程序的复杂度,变得可控。
  2、抽象化编程
    抽象化是数据和处理方法的结合,可以说是数据+处理方法="黑盒子",利于变化,隐藏了实现的细节,只对“要做什么”感兴趣,代码的抽象化把抽象的过程具体化了。这样的一个结果是我们不关心代码的实现只需要关注类具有的功能,拿到功能就可以调用,要是因为需求变化内部的修改也不会影响外部的调用,只要返回类型和数据正确。
 
  程序的重复是一个很大的问题:重复有以下的缺点:
  1、发现问题修改不方面,多处都要重复修改;
  2、增加代码量,浪费内存,难于管理;
  3、降低了程序的可读性和理解难度;
   进而影响开发效率降低生产力,所以程序重复是最需要避免的,也是面向对象的一个原则之一。对程序中出现的重复部分,相同功能的代码块,应该组合到一块一处利用,这就是DRY(Do not Repeat YourSelf)原则。
  3、面向复用、组件、面向服务
     对软件的要求越来越高,越来越复杂,人们在设计中积累了很多经验,由Gof总结命名并分类了23中模式,这就是设计模式。有些常见的模式我们开发中在用只是没注意到,比如:单例模式(全局一个对象)、迭代器(foreach循环)、组合(多重继承的替换)、代理(复杂对象先不生成委托给方法或某类执行)(详细请查阅资料)。也有些复杂的模式,足够学习设计模式即使你不是一个专业的设计师,也可以套用模式设计出来好的类。可以说设计模式是程序抽象化的延伸,类库、组件在实际的开发过程中被积累下来,作为下次项目中重用的模块以提高开发效率。大规模复杂的软件系统是基于很多组件、服务、平台的编程。
 三、面向对象的特征
  1、继承
     为什么要有继承呢?代码重复是一大问题,程序中重复的代码怎么办呢?这就需要有一种机制可以共用这部分重复的代码,又方便功能扩展,继承就是这样的。继承把很多重复的代码块、共用的方法属性在独立出来,称为父类,新生成的称为子类;子类继承父类的所有方法属性,也可以增加新的方法,当然也可以重写。      一个类可以有一个父类,这叫做单一继承;有多个父类这叫做多重继承。很显然单一继承的超集是多重继承,单一继承关系单一只有一个父类,实现起来也简单,不会发生混乱。
    多重继承就不一样了:
     类之间的关系复杂;
     哪个类继承了哪个类的功能不易理解;
     出现问题不易判明。
     结构复杂化,优先顺序模糊,功能冲突。
    所以我们在开发过程中说,类的继承层次不要太深,能满足要求就行。但是有的情况下是不得不用多重继承,比如:C#中的Stream类,下面有WriteStream、ReadStream、
  WriteReadStream等,只有两种处理方式,要么多重继承,要么组合在WriteReadStream类里有读写流的实例化。比如在现实生活中一位职员,他也可能是多种角色,即是编码员、经理又是活动的组织者等。
    但是java里没有多重继承。继承可以分为规格的继承:类有哪些方法,从外部看到的功能;实现的继承:类的实现采用了什么数据结构、算法。
    为解决多重继承带来的问题,java中引入了组合和接口的概念,变相的实现了多重继承的功能。
     组合:调用别的类来实现共通的功能。
     接口:接口是用来指定对象的外观,限制类的行为功能,跟具体的类没有关系,继承接口的类要负责实现接口定义的规则。下面找到一例java中多重继承的实现:
     interface lockingMin{
     void lock();
     void unlock();
     }
    class Lock{
    void lock(){
    ...
    }
   void unlock(){
   ....
   }
 }
    class printer implements lockingMin{
    final Lock lock=new Lock();
    void lock(){
    lock.lock();
   }
   void unlock(){
   lock.unlock;
  }
  }
    以上利用委托给具体的类实现的功能。
   interface  lockingMin{
      void lock();
      void unlock();
   }
    class lock implemens lockingMin{
    void lock(){
    ...
    }
    void unlock(){
    ...
    }
    }
    class printer {
   final lock =new lock();
   void spool(TextData text){
   this.lock.lock();
   ...
  this.lock.unlock();
  }
  }
  以上不使用委托,通过定义成属性来实现多重继承。
 2、封装
    封装就是上面说的数据抽象化编程,把实现看作一个类,一个黑盒子,不关心内部的实现细节,只关心外在的功能。
 3、多态
      多态是面向对象中最重要的一个特性。多态可以理解成:可以把不同种类的东西当成一个东西来使用,根据对象不同的类型来进行适当的处理,最常见的一个表现就是重载。函数名一样,参数和返回类型不同,在调用时不用考虑传递的参数和返回类型,就可以自动选择方法的调用。在C#中父类类型的变量可以用子类的实例化来赋值,也被叫做依赖替换原则。            
    多态性的好处:各种数据可以统一处理,它可以让程序只关注要处理什么,而不是怎么处理;根据对象的不同自动选择最合适的方法,而程序内容不发生冲突。
 四、数据类型的出现
      我们都知道计算机只能识别和处理二进制的数据,数组、字符串、复杂对象中内存的地址也是用整数来表示的,若出现差错,程序就不能正常执行,这就意味着用整数记录的类型地址,若是人工记录,无疑会增加很大的负担,数据类型是必须的。
    有数据类型的语言是静态语言,相反是动态语言(简单的这样说,比如js中也有预留的int、float等基础类型)。
  静态语言:在程序执行前从代码中就可以知道一切。程序的静态部分包括变量、方法的名称和类型以及控制程序的结构等等。最大的一个优点:在编译前就可以发现类型不匹配的错误,对代码进行优化,大大的减轻程序员的负担。最大的缺点:意味着所有的程序都是提前编译好直接生成可执行的代码,浪费内存。
  优点如下:
    (1)在编译期间能够发现类型不匹配的错误;
    在IDE开发工具中编译期间可以发现类型不匹配的错误,大大减轻了程序员的负担,不用在专门花费时间调试因为语法问题而出错的程序,提高了开发效率。
    (2)数据类型的信息不只是对编译器有用,对理解程序也有用;
    数据类型意味着可以获取更多的代码的信息,对调试程序有利,你可以插入断点或者即时调试代码,可以通过反射获取或修改程序的信息,无疑也增加了可读性。
    (3)IDE工具利用数据类型信息对程序进行大胆优化:
    IDE工具也就一个好处,开发、调试、测试、部署一体化,提供了很多快捷的方式,大大提高了效率;拿C# vs工具举例,编译期间可以自动匹配类型错误,代码提示功能,经过编译直接生成IL中间语言,JIT可以对代码进行提速优化,生成本地可执行指令;重构工具,方便管理多个工程,便于团队协作开发等,详细参见微软官方介绍。
     静态语言也是有缺点的,比如:灵活性问题,静态类型的本质限制了给某个变量只能赋值某种类型的对象(C#中有关键字var在运行时会确定对象的类型但是在编译期间var指定的对象不能调用特定类库中的方法,因为它只有在运行时根据上下文被确定);若不指定类型就没有办法写程序了,就要报错,程序的本质还是要处理业务逻辑,数据类型只是一些辅助信息。 
     动态语言:指的是在程序执行之前有些地方是不知道的,包括变量的值、执行时间和使用内存等情况。最大的一个优点是使程序变得简洁。编译期间不做类型检查,在运行程序调用方法时才会去查找被调用方法。这也是它的一个缺点,执行效率没有静态语言的块,边解释边执行,不运行是发现不了错误的。但是随着计算机性能的提高,对程序的灵活性、可扩展性可维护性比性能要求高。对于它的缺点也有办法避免的:
  1>执行时才能发现错误;可以通过完备的单元测试
  2>程序用到的线索少;java有JavaDoc技术文档,ruby也有RubyDoc文档参阅,js也有官方文档、社区、大量资源可用
  3>运行速度慢;随着计算机性能的提高,已经不重要了,灵活性、生产力可维护性更显得重要。
  以上把理解的记录下来,求讨论指正,大多的开发语言都是符合面向对象编程思想,现在基本上是常识性的东西了。

posted on 2013-11-17 20:38  yss小虾米  阅读(191)  评论(0编辑  收藏  举报

导航