`
nihao620
  • 浏览: 61479 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

java面向对象浅析系列1——三个基本特征

阅读更多

转载于  http://blog.csdn.net/hwalan/archive/2006/05/25/755251.aspx

 

众所周知,面向对象的三个基本特征是封装、继承和多态。

笔者所理解的封装是指将某事物的属性和行为包装到对象中,这个对象只对外公布需要公开的属性和行为,而这个公布也是可以有选择性的公布给其它对象。 在java中能使用private、protected、public三种修饰符或不用(即默认defalut)对外部对象访问该对象的属性和行为进行限 制。

笔者认为继承是子对象可以继承父对象的属性和行为,亦即父对象拥有的属性和行为,其子对象也就拥有了这些属性和行为。这非常类似大自然中的物种遗传。

封装和继承一般比较容易理解,而多态则不容理解,很容易理解错或者混淆概念。下面主要谈一谈笔者对多态的理解。

谈到多态,就需要先提到一些词汇,诸如重载、过载、覆盖、重写等等。笔者不对这些词汇的含义进行分析,而且对多态中的内容,每个人都会有自己的理 解,而且也都有各自的习惯叫法,正所谓仁者见仁,智者见智。因为笔者在工作和学习中主要是使用java,因此笔者更倾向于使用java中的固定用法,即 overriding(覆盖)和overload(过载)。多态则是体现在overriding(覆盖)上,而overload(过载)则不属于面向对象 中多态的范畴,因为overload(过载)概念在非面向对象中也存在。

overload(过载)是指可以编写相同名称但不同形式的函数,C语言中也有这种特性,而C语言是面向过程不是面向对象的。overload(过 载)要求不同形式的同名函数必须有不相同的参数列表,不同的参数列表包括参数的类型不一致、参数个数不一致、不同类型的参数的顺序不一致。而如果参数列表 相同仅仅是函数返回值类型不一致则是非法的,因为编译器可能无法判断应该使用哪个返回类型的函数。请看以下示例:

         有以下两个函数原型:

                    int count();

                    double count();

         程序中可以有以下几种方式调用:

             1.  int iCount = count();

             2.  double dCount = count();

             3.  count();

         在上面的1和2的调用示例中,编译器似乎能够判断出应该调用的函数从而做出正确的选择,然而很显然,对于3的调用编译器就无能为力了,而3的写法是完全合法并且实际上也会经常用到。

overriding(覆盖)是笔者所认为的面向对象中的多态,因为overriding(覆盖)是与继承紧密联系,是面向对象所特有的。多态是指 父对象中的同一个行为能在其多个子对象中有不同的表现。也就是说子对象可以使用重写父对象中的行为,使其拥有不同于父对象和其它子对象的表现,这就是 overriding(覆盖)。这种特性非常类似大自然遗传中的变异,变异使得大自然变得丰富多彩,而多态使面向对象富有魔力。下面通过一个具体示例来体 会一下多态的魔力。

            有一个父类A:

                  public class A {

                          public void methodA() {

                                  System.out.println("This is Parent of A.");

                          }

                  }
 

            父类A有以下三个子类:

                  public class B1 {

                          public void methodA() {

                                  System.out.println("This is Children of B1.");

                          }

                  }

                  public class B2 {

                          public void methodA() {

                                  System.out.println("This is Children of B2.");

                          }

                  }

                  public class B3 {

                  }
 

             上面的子类B!和B2都重写了父类A的方法methodA,而B3则没有。下面我们用实际的调用语句看一看。

              1.    A a1 = new A();

              2.   A a2 = new B1();

              3.    A a3 = new B2();

              4.    A a4 = new B3();

              5.    a1.methodA();

              6.    a2.methodA();

              7.    a3.methodA();

              8.    a4.methodA();

              以上语句的运行结果会如下:

                    This is Parent of A.

                    This is Children of B1.

                    This is Children of B2.

                    This is Parent of A.

             从上面的运行结果可以看到,第五行是指向父类对象实例的引用调用方法methodA,执行也是父类的方法;第六、七行虽然是用类A的对象引用调用方法 methodA,但是由于对象引用是指向相应的子类对象的实例,程序正确执行了子类的方法,并没有产生歧义;第八行是指向子类对象B3的实例的引用调用方 法methodA,而由于子类B3没有对方法methodA进行overriding(覆盖),也就是直接继承了父类的行为,所以执行结果与第五行一样。 从这里我们能够轻易体会到多态的魔力。

这一次先写到这里,暂且作为抛砖引玉,不妥之处还望大家指正。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics