1. 程式人生 > >JAVA學習---抽象類,介面

JAVA學習---抽象類,介面

週日我們進一步學習了抽象類,介面,還好好分析了四種許可權修飾符的特性。

抽象類

  • 定義: 我們先從一個例子引出抽象類的定義:比如我說一隻動物,你知道我說的是什麼具體動物嗎?只有看到了具體的動物,你才知道,這是什麼動物。 所以說,動物本身並不是一個具體的事物,而是一個抽象的事物。只有真正的貓,狗才是具體的動物。同理,我們也可以推想,不同的動物吃的東西應該是不一樣的,所以,我們不應該在動物類中給出具體體現,而是應該給出一個宣告即可。所以,在Java中,一個沒有方法體的方法應該定義為抽象方法,而類中如果有抽象方法,該類必須定義為抽象類。父類當中不給出所有子類共性功能的實現,強制子類根據各自的差異性去重寫
  • 抽象類的特點: 1.抽象類和抽象方法必須用abstract關鍵字修飾

抽象類:abstract class 類名{} 抽象方法:public abstract void 方法名(); //抽象方法:只給出方法宣告,不給出方法的具體實現

2.抽象類不一定有抽象方法,有抽象方法的類一定是抽象類。可是抽象類中的構造方法不能進行例項化,因此它沒有意義。 3.抽象類不能直接例項化,而是需要按照多型的方式,由具體的子類例項化,即抽象類多型。 4.如果一個類中如果有了抽象方法,則此類必須為抽象類。 5.抽象類的子類要門時抽象類,要麼 必須重寫抽象類中的所有抽象方法。所以說抽象類的成員方法是強制要求子類做的事情。

//定義抽象類Animal寫了兩個抽象方法eat(),sleep();
public abstract class Animal {

    public abstract void eat();
    public abstract void sleep();
}
//定義子類Cat繼承抽象類Animal
public class Cat extends Animal{
    private String name;
    private int age;

    public String getName() {
        return name;
    }
    public void
setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override //重寫父抽象類中的所有方法。 public void eat() { System.out.println("貓吃魚"); } @Override public void sleep() { System.out.println("貓經常睡覺"); } public void catcheMouser(){ //定義了一個Cat獨有的方法 System.out.println("貓抓老鼠"); } } //定義子類Dog繼承抽象類Animal public class Dog extends Animal{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override ////重寫父抽象類中的所有方法。 public void eat() { System.out.println("夠吃骨頭"); } @Override public void sleep() { System.out.println("狗晚上睡覺"); } public void lookDoor(){ //定義了一個Dog獨有的方法 System.out.println("狗看門"); } } //定義測試類test public class Test4 { public static void main(String[] args) { Animal an = new Dog(); //多型 an.sleep(); an.eat(); Dog dog = (Dog) an; //向下轉型 dog.setName("旺財"); dog.setAge(5); System.out.println(dog.getName()); System.out.println(dog.getAge()); dog.lookDoor(); System.out.println("-----------------------"); an = new Cat(); an.eat(); an.sleep(); Cat cat = (Cat) an; //向下轉型 cat.setName("小白"); cat.setAge(2); cat.catcheMouser(); System.out.println(cat.getAge()); System.out.println(cat.getName()); } }

在這裡插入圖片描述 以上的例子充分展示了抽象類以及多型的使用方法。子類繼承抽象父類,並且重寫父類中的所有方法,同時定義了自身特有的方法,並通過多型向下轉型呼叫使用。

注意抽象類關鍵字abstract和一些關鍵字是衝突的。 a. private 衝突(abstract定義抽象類,它強制要求子類重寫方法,而private有將它私有,不許繼承和重寫,因此衝突)。 b. final 衝突(與private相似) c. static 不能共存,這樣無意義(static 修飾的方法算不上重寫)

上面我們討論了一些修飾符的特點,那我們就來詳細討論一下修飾符: 四種許可權修飾符:private(私有) ,預設,protected(受保護的),public(公共的)

  • 許可權表
本類 同一個包下(子類和無關類) 不同包下(子類) 不同包下(無關類)
private Y
預設 Y Y
protect Y Y Y
public Y Y Y Y

許可權修飾符:private,預設的,protected,public 狀態修飾符:static,final 抽象修飾符:abstract

介面

  • 概述: 我們繼續之前的案例,貓狗除了吃飯睡覺(繼承)我們想想狗一般就是看門,貓一般就是作為寵物了(多型,重寫)。但是,現在有很多的馴養員或者是馴獸師,可以訓練出:貓鑽火圈,狗跳高,狗做計算等。而這些額外的動作,並不是所有貓或者狗一開始就具備的,這應該屬於經過特殊的培訓訓練出來的。所以,這些額外的動作定義到動物類中就不合適,也不適合直接定義到貓或者狗中,因為只有部分貓狗具備這些功能。 所以,為了體現事物功能的擴充套件性,Java中就提供了介面來定義這些額外功能,並不給出具體實現,將來哪些貓狗需要被培訓,只需要這部分貓狗把這些額外功能實現即可 介面:定義一些擴充套件功能或者規範.哪個類想要具備這些擴充套件功能可以實現這個介面。
  • 定義: 關鍵字:interface 格式:interface 介面名{} 實現:implements class 類名 implements 介面名{}
  • 特點: 1.介面中的成員變數前面有預設修飾符 public static final 。 2.方法前面預設有修飾符 public abstract 你可以省略不寫,建議你寫出來 3.介面中所有的方法都是抽象方法,抽象類中可以有抽象,也可以有非抽象方法 4.介面中沒有構造方法 5.介面中所有的成員變數都是公共的靜態常量 6.介面的子類可以是抽象類 7.介面跟介面之間可以繼承,而且是多繼承 8.介面不能建立物件,即介面不能例項化,如果想例項化要按照多型的方式來例項化。 9.介面可以實現多繼承,而default關鍵字可以允許在介面中定義預設類,這也相當於變相承認java多繼承。

介面例項:

//定義抽象父類Animal
public abstract class Animal {
    public abstract void eat();
    public  abstract void sleep();
}
//定義介面MyInterface
public interface MyInterface {
    int NUM = 100;
    (public static final)  double D = 100;  //括號裡的可以沒有,預設修飾符。
    (public abstract) void fire();
    void hehe();

}
//implements 實現 用來實現一個介面的
//定義子類Dog,繼承抽象父類Animal,同時呼叫介面MyInterface
public class Dog extends Animal implements MyInterface{
	//先重寫抽象父類中的方法eat(),sleep().
    @Override
    public void eat() {
    }
    @Override        
    public void sleep() {
    }
    //例項化介面的方法fire(),jump().
    @Override
    public void fire() {      
        System.out.println("狗鑽火圈了");
    }
    @Override
    public void jump() {
        System.out.println("狗跳高了");
    }
}
//test測試類
public class Test {
    public static void main(String[] args) {
        //介面不能例項化
        MyInterface my = new Dog(); //多型的形式
        my.fire();
        my.jump();
    }
}

在這裡插入圖片描述

  • !引數傳遞: 下面我們來說說java中的引數傳遞。 1.如果一個方法的形參要一個 型別,則傳一個該類的物件。 2.如果一個方法的形參要一個 抽象類型別 那麼你就傳該類的一個子類物件 。 3.如果一個方法的返回值型別要一個 介面 型別 你就返回一個該介面的子類物件。 4.如果一個方法的返回值型別 要一個==類= 型別,你就返回一個該類的物件。 這裡引數的傳遞給了我們一個很好的程式設計方法,鏈式程式設計(連調),這樣可以簡化程式設計的複雜性,但是需要我們對引數的傳遞有深刻的理解。

  • 內部類: 1.定義: 將一個類 定義到另一個類的內部,我們就稱之為內部類;將類A 定義到B類當中 我們稱A為內部類,B 我們可以叫外部類;同時根據定義位置的不同,我們分為成員內部類,區域性內部類; 成員內部類:內部類在外部類的成員位置。 區域性內部類:內部類在外部類的區域性位置(方法中)。 2.內部類的特點: (1):內部類可以直接訪問外部類的成員,包括私有的; (2):內部類被private 修飾後,外界不能建立內部類物件; (3):static 可以修飾內部類,同時靜態內部類只能訪問外部類的靜態成員; (4):區域性內部類訪問區域性變數必須用final修飾 在JDK1 .8之後預設就加上了; 因為區域性變數會隨著方法的呼叫完畢而消失,這個時候,區域性物件並沒有立馬從堆記憶體中消失,還要使用那個變數。 為了讓資料還能繼續被使用,就用fianl修飾,這樣,在堆記憶體裡面儲存的其實是一個常量值。

public class Outer {
    int num=100;
    private String name="abc";
    public void waiMethod(){
        //定義區域性內部類
        //內部類可以直接訪問外部類的成員 包括私有的
        class Inner{
            int nei=10;
            public void neiShow(){
                System.out.println(num);
                System.out.println(name);
            }
            public void neiTest(){
                waiTest();
            }
        }
        Inner inner = new Inner();
        System.out.println(inner.nei);
        inner.neiShow();
        inner.neiTest();
    }
    private void waiTest(){
        System.out.println("我是外部類的私有方法");
    }
}
public class Test5 {
    public static void main(String[] args) {
        //區域性內部類,外界無法直接建立其物件
        new Outer().waiMethod();
    }
}

在這裡插入圖片描述