Java入門之面向對象-多態(tài)

多態(tài)

多態(tài)是面向對象編程中最后一個(封裝、繼承、多態(tài))也是最重要的特征。

程序設計當中,多態(tài)意味著,允許不同類的對象對同一消息做出不同的響應。

多態(tài)分為:

  1. 編譯時多態(tài) (設計時多態(tài)方法重載)
  2. 運行中多態(tài) (程序運行時動態(tài)決定調用哪個方法)


    image.png

一般所說的java中的多態(tài)大多是運行時多態(tài)。

必要條件

  • 滿足繼承關系
  • 父類引用指向子類對象

示例

image.png

新建一個Animal類,作為動物基類,有兩個屬性,name、month,和一個eat方法。
Animal的子類中有自己特有的子類屬性和方法,
Cat中有weight、run(),
Dog中有sex、sleep()。
且都重寫了父類Animal中的eat()方法。

新建Animal.java:

public class Animal {
    private String name;
    private int month;

    public Animal(){

    }

    public Animal(String name, int month){
        this.name = name;
        this.month = month;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public void eat(){
        System.out.println("動物都有吃東西的能力");
    }
}

新建Cat.java:

public class Cat extends Animal{
    private double weight;

    public Cat(){

    }

    public Cat(String name, int monnth, double weight){
        super(name, monnth);
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public void run(){
        System.out.println("小貓快樂地奔跑");
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("貓吃魚");
    }
}

新建Dog.java:

public class Dog extends Animal {
    private String sex;

    public Dog(){

    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Dog(String name, int month, String sex){
        this.setMonth(month);
        this.setName(name);
        this.setSex(sex);
    }

    public void sleep(){
        System.out.println("小狗午睡");
    }

    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

然后在定義一個測試文件Test.java:

public class Test {
    public static void main(String[] args){
        Animal one = new Animal();
        Animal two = new Cat();
        Animal three = new Dog();
        one.eat();
        two.eat();
        three.eat();

    }
}

運行Test.java


image.png

雖然都是吃這種行為,也同樣都是Animal類型的引用,但是隨著它具體在程序運行時實例化的對象類型不同,那么它的執(zhí)行的具體行為能力是不一樣的,這就是在java中多態(tài)的表現(xiàn)。

向上轉型

父類引用指向子類實例:Animal one = new Animal();
把一個子類對象轉型為父類對象,向上轉型(隱式轉型、自動轉型),代碼中是父類引用指向子類實例,
父類引用指向子類實例,可以調用子類重寫父類的方法以及父類派生的方法,無法調用子類獨有的方法。

注意:

父類中的靜態(tài)方法無法被子類重寫,所以向上轉型之后,只能調用父類原有的靜態(tài)方法

向下轉型(強制類型轉換)

子類引用指向父類實例,必須進行強制類型轉換,可以調用子類特有的方法。
必須滿足轉型條件才能強轉。

instanceof運算符可以進行判斷,左邊對象是否是他右邊對象的實例,換句話說就是左側對象是否滿足右側對象類型的特征如果是,返回true。

if (obj instanceof Cat)

父類中的靜態(tài)方法(含有static修飾的方法),只能被子類繼承使用,無法被子類重寫。

public static void say(){

}

抽象類

Java中使用抽象類,限制實例化

public abstract class A{

}

通過abstract 修飾的類叫做抽象類。

當一個類為抽象類時,就不允許實例化了,可以通過向上轉型指向子類。

抽象類應用場景:

某個父類只是知道其子類應該包含怎樣的方法,但無法準確知道這些子類如何實現(xiàn)這些方法。
當我們將父類設置為抽象類時,既可以借由父類和子類的繼承關系限制子類隨意性,同時也在一定程度上避免了無意義的實例化。

抽象方法

abstract 修飾的方法為抽象方法。
抽象方法要求:

  1. 不允許包含方法體
  2. 子類中必須重寫父類中的抽象方法
  3. 如果不重寫,子類自己必須被定義為抽象類
  4. 包含抽象方法的類必須是抽象類
總結:
  1. 抽象類不能直接實例化
  2. 子類如果沒有重寫父類所有的抽象方法,則也要定義為抽象類
  3. 抽象方法所在的類一定是抽象類
  4. 抽象類中可以沒有抽象方法
  5. static、final、private關鍵字不能與abstract 并存。

接口

當多個類型之間具有相同的行為能力的時候,java中可以借由接口來進行類型之間的聯(lián)系。

通過接口可以解決java當中單繼承所帶來的一些類型無法共享的問題。

  • 接口定義了某一批類所需要的遵守的規(guī)范
  • 接口不關心這些類的內部數(shù)據(jù),也不關心這些類里方法的實現(xiàn)細節(jié),它只規(guī)定這些類里必須提供某些方法。
語法:
[修飾符] interface 接口名 [extends 父接口1,父接口2...]
{
  零個到多個常量定義...
  零個到多個抽象方法定義...
  零個到多個默認方法定義...(jdk1.8新增)
  零個到多個靜態(tài)方法方法的定義...(jdk1.8新增)
}
  • 接口可以實現(xiàn)多繼承,即一個子接口可以同時繼承多個父接口
  • 實現(xiàn)接口的類如果不能實現(xiàn)所有接口中待重寫的方法,則必須設置為抽象類。
  • 一個類可以繼承自一個父類,同時實現(xiàn)多個接口

內部類

在Java中,可以將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內部類。與之對應,包含內部類的類稱為外部類。

內部類分為四種:

  • 成員內部類
  • 靜態(tài)內部類
  • 方法內部類
  • 匿名內部類
優(yōu)勢:內部類提供了更好的封裝,可以把內部類隱藏在外部類之內,不允許同一個包的其他類訪問該類,更好的實現(xiàn)了信息隱藏。
1.成員內部類

內部類中最常見的就是成員內部類,也稱為普通內部類。
如下:

package com.imooc.people;

//外部類
public class Demo {
    int name;

    public He getSex(){
        return new He();
    }
    
    //成員內部類
    class He{
        public String sex(){
            return "男";
        }
    }
}

獲取內部類對象實例的三種方式:

public static void main(String[] args){
    Demo a = new Demo();
    a.name = 3;
    //方式一
    Demo.He h = new Demo().new He();
    //方式二
    h = a.new He();
    //方式三
    a.getSex();
}
  • 內部類在外部使用時,無法直接實例化,需要借由外部類信息才能完成實例化
  • 內部類的訪問修飾符,可以任意,但是訪問范圍會受到影響
  • 內部類可以直接訪問外部類的成員;如果出現(xiàn)同名屬性,優(yōu)先訪問內部類中定義的
  • 可以使用外部類.this.成員的方式,訪問外部類中同名的信息
  • 外部類訪問內部類信息,需要通過內部類實例,無法直接訪問
  • 內部類編譯后.class文件命名:外部類$內部類.class
2.靜態(tài)內部類
  • 靜態(tài)內部類中,只能直接訪問外部類的靜態(tài)成員,如果需要調用非靜態(tài)成員,可以通過對象實例
  • 靜態(tài)內部類對象實例時,可以不依賴于外部類對象
  • 可以通過外部類.內部類.靜態(tài)成員的方式,訪問內部類中的靜態(tài)成員
  • 當內部類屬性與外部類屬性同名時,默認直接調用內部類中的成員;
  • 如果需要訪問外部類中的靜態(tài)屬性,則可以通過 外部類.屬性 的方式;
  • 如果需要訪問外部類中的非靜態(tài)屬性,則可以通過 new 外部類().屬性的方式;
3.方法內部類

定義在外部類方法中的內部類,也稱為局部內部類。


image.png

方法的約束對方法內部類同樣有效。

  • 定義在方法內部,作用范圍也在方法內
  • 和方法內部成員使用規(guī)則一樣,class前面不可以添加public、private、protected、static
  • 類中不能包含靜態(tài)成員
  • 類中可以包含final、abstract修飾的成員
4.匿名內部類

匿名內部類

public static void main(String[] args) {
        PersonTest test=new PersonTest();

        test.getRead(new Person(){
            {
                //構造代碼塊
            }
            @Override
            public void read() {
                System.out.println("男生喜歡看科幻類書籍");
            }
            
        });
        test.getRead(new Person(){
            @Override
            public void read() {
                System.out.println("女生喜歡讀言情小說");
            }
            
        });
    }

}
  • 匿名內部類沒有類型名稱、實例對象名稱
  • 編譯后的文件命名:外部類$數(shù)字.class
  • 無法使用private、public、protected、abstract、static修飾
  • 無法編寫構造方法,可以添加構造代碼塊
  • 不能出現(xiàn)靜態(tài)成員
  • 匿名內部類可以實現(xiàn)接口也可以實現(xiàn)繼承父類,但是不可兼得

如果內容對你有幫助,記得關注作者給個贊哦~,后續(xù)會持續(xù)更新。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1 面向對象No6 面向對象 OO Object Oriented 編程時以對象為單元,封裝數(shù)據(jù)和邏輯,以此提...
    征程_Journey閱讀 1,261評論 0 2
  • 面向對象筆記 一、 對象在內存中的存放方法以及被調用過程 class文件首先被加載到方法區(qū)中的class文件內容區(qū)...
    VictorBXv閱讀 568評論 0 2
  • 設計模式概述 在學習面向對象七大設計原則時需要注意以下幾點:a) 高內聚、低耦合和單一職能的“沖突”實際上,這兩者...
    彥幀閱讀 3,888評論 0 14
  • 有一個朋友,和他聊天時,他的言談里時不時冒出一個某某長,某某局的名字,他一直說他很忙,和某局吃飯,和某領導出差。有...
    琳娜911閱讀 278評論 3 4
  • 夜迷失在無盡的黑色, 一條蜿蜒的河流, 一盞橘色的燈, 孤獨是一種懲罰, 以至于呼吸的時候就像得了肺炎一般, 總會...
    綠嘴鸚鵡閱讀 316評論 2 7

友情鏈接更多精彩內容