• 那些年一起学过的面向对象之:4 面向对象的三大特征:封装、继承、多态


    面向对象的三大特征

    • 封装(Encapsulation)

    封装,可以望文生义,即将东西封装起来,不让别人知道,当然,自己可以知道,指定信得过的人也可以知道。

    封装将数据和行为封装起来,并对对象的使用者隐藏了数据的实现方式。

    其实,一个对象就是封装了数据和操作这些数据的代码的逻辑实体。

    在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。这就为对象内部数据提供了保护的作用,防止被意外修改。

    好处:

    1提高重用性(封装)

    2提高可靠性(隐藏)

    3方便对象的使用者使用(隐藏了复杂性)

    • 继承

    现实世界中,很多东西都不是相互孤立的,它们往往具有相同的特征,也存在差异。

     

    上图反应了人类的派生关系。最高层往往具有最普遍的特征,越往下层越具体,并且下层包含上层的特征。

    在程序设计中,这种关系叫做继承。一个类从另外一个类派生出来,派生类继承了父类的所有特性,并且可以添加自己的特性。通过继承所创建的新类叫做子类(或派生类),被继承的类叫做父类(或基类、超类),继承的过程是从一般到具体的过程。

    继承是is-a的关系,是一种用于表示特殊与一般的关系。

    在考虑使用继承时,如果两个类的关系是“is-a”的关系,即说“XXX是XXX”成立的话,继承关系就成立了。如:说“男人是人”,说得通吧;要是说“王八是人”,看人家不!@&#%#¥。

    在面向对象中,继承是非常优秀的语言机制,有如下优点:

    1提高代码的重用性;

    2代码共享,减少创建类的工作量,因为,每个子类都拥有父类的属性和方法;

    3提高代码的可扩展性;

    4子类可以形似父类,又可以异于父类。

    当然,也有缺点:

    1继承是入侵的。只要继承,就必须拥有父类的所有属性和方法;

    2降低了代码的灵活性。子类必须拥有父类的所有属性和方法,让子类的自由世界多了约束。试想,要是“老爹”是个品行不正,是个酒鬼,“儿子”被坑大了。

    3增强了耦合性。当父类被修改时,必须考虑子类的修改,可能导致大片的代码需要重构。

    • 多态(polymorphisn)

    所谓多态,就是父类型的引用可以指向子类型的对象(或接口类型的引用可以指向实现该接口的类的实例)

    如: 

     
    //动物
    public class Animal {
         //动物都会
         public void cry() {
             System.out.println( "(动物叫)" );
         }
    }
      
      
    //狗,继承于动物
    public class Dog extends Animal {
         //狗有它自己的叫法
         @Override
         public void cry() {
             System.out.println( "汪汪" );
         }
    }
      
    public class Test {
         public static void main(String[] args) {
             //Dog dog = new Dog();
             //dog.cry();        
             Animal animal = new Dog(); //父类型的引用可以指向子类型的对象
             animal.cry(); //输出:汪汪
         }
    }

    实现多态,有二种方式:覆盖、重载。

    覆盖:是指子类重新定义父类的方法。

    重载:是指方法名相同,参数列表不同。

    可以这么理解:

    覆盖,不但不用祖宗那套功夫,而且还自己创一套新的代替祖宗那套;

    重载,你是你,我还是我。

    覆盖,为纵向关系;重载,为横向关系。

    接下来应该注意了。

    1其实,重载的概念并不属于“面向对象编程”,重载的实现是编译器根据函数不同的参数列表,对同名函数的名称进行修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如有2个同名函数function func(p:integer):integer和function func(p:string):integer,那么编译器做过修饰后的函数名称可能是int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住是静态)。也就是说,它们的地址在编译期就绑定了(早绑定)。因此,重载和多态无关!

     

    2真正和多态相关的是“覆盖”。当子类重新定义了父类的函数后,父类指针根据赋给它的不同的子类指针,动态(记住是动态)的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。

     

    3结论:

    a重载只是一种语言特性,与多态无关,与面向对象也无关。引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚邦定,它就不是多态。”

    b多态是晚绑定;

    c多态是一种运行期行为,不是编译器的行为;

    d不要把重载理解为多态,重载是编译时就确定的;

    e构成多态的条件:继承、重写、父类引用子类的对象。

     

    4那么,多态的作用是什么呢?

    我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类)。它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用。多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

  • 相关阅读:
    C博客作业00我的第一篇博客
    html5 canvas中CanvasGradient对象用法
    Java 多线程总结
    查看和设置MySQL数据库字符集(转)
    (原)QQ表情弹出框的制作(凑热闹)
    [转]模版方法(Template Method)
    .net Smtp Email工具V1
    [转]迭代器模式(Iterator Pattern)
    (原)可自定义Item子项的ListBar控件V1.0
    使用C#实现ADSL自动拨号
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3144965.html
Copyright © 2020-2023  润新知