最新公告
  • 欢迎光临数据科学与编程,我们是数据学科学兴趣交流小组立即加入我们
  • Java基础系列:Java面向对象编程的三大特性

    Java面向对象编程作为一种编程思想,有三大特性,封装,继承,多态。对于一个类而言, 如何封装 呢?继承是父类和子类的关系, 继承关系如何实现的呢?父类和子类继承时的方法体是怎么样的关系呢?多态是多个类之间的关系,类有不同的行为和属性,其他类也有这样的方法和属性,就实现了多态的关系,不同类的多态实现是怎么样实现的呢?

    一:面向对象编程三大特性

    面向对象编程是利用 类和对象编程的一种思想。万物可归类,类是对于世界事物的高度抽象 ,不同的事物之间有不同的关系 ,一个类自身与外界的封装关系,一个父类和子类的继承关系, 一个类和多个类的多态关系。万物皆对象,对象是具体的世界事物,面向对象的三大特征封装,继承,多态,封装,封装说明一个类行为和属性与其他类的关系,低耦合,高内聚;继承是父类和子类的关系,多态说的是类与类的关系。

    1. 封装

    什么是封装?

    把客观事物封装成抽象的类,并且把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。也 就 是 说抽象数据类型对数据信息以及对数据的操作进行打包,将其变成一个不可分割 的实体,在这个实体内部,我们对数据进行隐藏和保密,只留下一些接口供外部调用。

    简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。

    封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。

    就好比一个烤面包机,我们把面包(数据)放进去,按下开关,过了一会,它就会自动弹出烤好的面包(处理后的信息),而这个过程是怎么烤的(对数据的操作),我们是不需要知道的。

    为什么需要封装?

    • 隐藏一个类中不需要对外提供的实现细节;

    • 属性的封装:使用者只能通过事先定制好的方法来访问数据,可以方便地加入逻辑控制,限制对属性的 不合理操作;

    • 方法的封装:使用者按照既定的方式调用方法,不必关心方法的内部实现,便于使用;便于修改,增强 代码的可维护性;

    如何封装?

    利用权限修饰符来描述方法体或属性。private修饰的属性或方法为该类所特有,在任何其他类中都不能直接访问;default修饰的属性或方法具有包访问特性,同一个包中的其他类可以访问;protected修饰的属性或方法在同一个中的其他类可以访问,同时对于不在同一个包中的子类中也可以访问;public修饰的属性或方法外部类中都可以直接访问。

    封装类似于黑箱操作,其设计要求是低耦合,高内聚。一个具体复杂的对象有很多的属性和方法,有些需要公开,有些不需要公开,就好比一个具体的人的信息,有些是public,有些是private,而有些是protecred,别人问到的时候对于怎么样的信息都有不同的态度。根据与这个人的关系来回答问题,封装的结果是输出结果,不问过程,其中,public是可以被任何变量访问的,private是该类私有的,protected类是受保护的,可以被该类所述的包内的所有的其他类访问,其子类也可以访问。

    比如我们将一个房子看做是一个对象,里面的漂亮的装饰,如沙发、电视剧、空调、茶桌等等都是该房子的私有属性,但是如果我们没有那些墙遮挡,是不是别人就会一览无余呢?没有一点儿隐私!就是存在那个遮挡的墙,我们既能够有自己的隐私而且我们可以随意的更改里面的摆设而不会影响到其他的。但是如果没有门窗,一个包裹的严严实实的黑盒子,又有什么存在的意义呢?所以通过门窗别人也能够看到里面的风景。所以说门窗就是房子对象留给外界访问的接口。

    2.继承

    什么是继承?

    继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

    在本职上是特殊——一般的关系,即常说的is-a关系。子类继承父类,表明子类是一种特殊的父类,并且具有父类所不具有的一些属性或方法。从多种实现类中抽象出一个基类,使其具备多种实现类的共同特性 ,当实现类用extends关键字继承了基类(父类)后,实现类就具备了这些相同的属性。

    继承的类叫做子类(派生类或者超类),被继承的类叫做父类(或者基类)。

    比如从猫类、狗类、虎类中可以抽象出一个动物类,具有和猫、狗、虎类的共同特性(吃、跑、叫等)。

     

    如何实现继承?

    Java通过extends关键字来实现继承,父类中通过private定义的变量和方法不会被继承,不能在子类中直接操作父类通过private定义的变量以及方法。

    继承的优点:继承避免了对一般类和特殊类之间共同特征进行的重复描述,通过继承可以清晰地表达每一项共同特征所适应的概念范围——在一般类中定义的属性和操作适应于这个类本身以及它以下的每一层特殊类的全部对象。运用继承原则使得系统模型比较简练也比较清晰。

    继承有哪些原则?

     

    成员变量的继承原则 具体的原则如下:

    • 能够继承父类的public和protected成员变量;不能够继承父类的private成员变量;

    • 对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

    • 对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。

     

    1.方法的重写

    子类如果对继承的父类的方法不满意(不适合),可以自己编写继承的方法,这种方式就称为方法的重写.通过重写父类的方法,可以用自身的行为代替父类的行为。当调用方法时会优先调用子类的方法。重写要注意:  a、返回值类型  b、方法名  c、参数类型及个数

    都要与父类继承的方法相同,才叫方法的重写。

    重载和重写的区别:

     

    • 方法重载:在同一个类中处理不同数据的多个相同方法名的多态手段。

    • 方法重写:相对继承而言,子类中对父类已经存在的方法进行区别化的修改

    2. 继承初始化顺序

    父类的构造器调用以及初始化过程一定在子类的前面

    1、初始化父类再初始化子类  

    2、先执行初始化对象中属性,再执行构造方法中的初始化。

    基于上面两点,我们就知道实例化一个子类,java程序的执行顺序是:

    父类对象属性初始化—->父类对象构造方法—->子类对象属性初始化—>子类对象构造方法

    下面有个形象的图:

    运行结果:

    3.多态

    所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

    比如你是一个酒神,对酒情有独钟。某日回家发现桌上有几个杯子里面都装了白酒,从外面看我们是不可能知道这是些什么酒,只有喝了之后才能够猜出来是何种酒。你一喝,这是剑南春、再喝这是五粮液、再喝这是酒鬼酒….在这里我们可以描述成如下:

    酒 a = 剑南春

    酒 b = 五粮液

    酒 c = 酒鬼酒

    这里所表现的的就是多态。剑南春、五粮液、酒鬼酒都是酒的子类,我们只是通过酒这一个父类就能够引用不同的子类,这就是多态——我们只有在运行的时候才会知道引用变量所指向的具体实例对象。

    诚然,要理解多态我们就必须要明白什么是“向上转型”。在继承中我们简单介绍了向上转型,这里就在啰嗦下:在上面的喝酒例子中,酒(Win)是父类,剑南春(JNC)、五粮液(WLY)、酒鬼酒(JGJ)是子类。我们定义如下代码:

     

     

     

    在这里我们这样理解,这里定义了一个Wine 类型的a,它指向JNC对象实例。由于JNC是继承与Wine,所以JNC可以自动向上转型为Wine,所以a是可以指向JNC实例对象的。这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。

     

    但是向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们。所以父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在与子类中的方法和属性它就望尘莫及了。



    分析:在这个程序中子类JNC重载了父类Wine的方法fun1(),重写fun2(),而且重载后的fun1(String a)与 fun1()不是同一个方法,由于父类中没有该方法,向上转型后会丢失该方法,所以执行JNC的Wine类型引用是不能引用fun1(String a)方法。而子类JNC重写了fun2() ,那么指向JNC的Wine引用会调用JNC中fun2()方法。

    所以对于多态我们可以总结如下:

    指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。

    对于面向对象而已,多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。

    原文链接:https://blog.csdn.net/weixin_41792162/article/details/83684384

    本站上原创文章未经作者许可,不得用于商业用途,仅做学习交流使用,本站免责声明。转载请注明出处,否则保留追究法律责任的权利。《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权
    数据科学与编程 » Java基础系列:Java面向对象编程的三大特性

    发表评论

    • 52会员总数(位)
    • 312资源总数(个)
    • 31本周发布(个)
    • 3 今日发布(个)
    • 331稳定运行(天)

    提供最优质的博文资源集合

    立即阅览 了解详情