关闭

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

标签: java编译器语言class工作c
4013人阅读 评论(3) 收藏 举报
分类:

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

笔者所理解的封装是指将某事物的属性和行为包装到对象中,这个对象只对外公布需要公开的属性和行为,而这个公布也是可以有选择性的公布给其它对象。在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(覆盖),也就是直接继承了父类的行为,所以执行结果与第五行一样。从这里我们能够轻易体会到多态的魔力。

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

(后记:忽见笔者抛一转向众网友,不料引来“众怒”,众网友每人手中按着一个美玉齐刷刷向笔者仍来,活活将笔者埋在了美玉堆成的山中。 :) ---------------------------------------发财了!笔者窃喜!)

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:31555次
    • 积分:397
    • 等级:
    • 排名:千里之外
    • 原创:4篇
    • 转载:15篇
    • 译文:0篇
    • 评论:4条
    文章分类
    最新评论