抽象類和介面用法 Is-a 關係 vs Has-a 功能

何時使用抽象類:在多個相關物件之間實現相同或不同的行為

何時使用介面:通過多個不相關的物件實現合同

抽象類建立是一種關係,而介面提供具有能力。

這可以在下面的程式碼中看到:

public class InterfaceAndAbstractClassDemo{
    public static void main(String args[]){
        
        Dog dog = new Dog("Jack",16);
        Cat cat = new Cat("Joe",20);
            
        System.out.println("Dog:"+dog);
        System.out.println("Cat:"+cat);
        
        dog.remember();
        dog.protectOwner();
        Learn dl = dog;
        dl.learn();
                
        cat.remember();
        cat.protectOwner();
        
        Climb c = cat;
        c.climb();
        
        Man man = new Man("Ravindra",40);
        System.out.println(man);
        
        Climb cm = man;
        cm.climb();
        Think t = man;
        t.think();
        Learn l = man;
        l.learn();
        Apply a = man;
        a.apply();
    }
}

abstract class Animal{
    String name;
    int lifeExpentency;
    public Animal(String name,int lifeExpentency ){
        this.name = name;
        this.lifeExpentency=lifeExpentency;
    }
    public abstract void remember();
    public abstract void protectOwner();
    
    public String toString(){
        return this.getClass().getSimpleName()+":"+name+":"+lifeExpentency;
    }
}
class Dog extends Animal implements Learn{
    
    public Dog(String name,int age){
        super(name,age);
    }
    public void remember(){
        System.out.println(this.getClass().getSimpleName()+" can remember for 5 minutes");
    }
    public void protectOwner(){
        System.out.println(this.getClass().getSimpleName()+ " will protect owner");
    }
    public void learn(){
        System.out.println(this.getClass().getSimpleName()+ " can learn:");
    }
}
class Cat extends Animal implements Climb {
    public Cat(String name,int age){
        super(name,age);
    }
    public void remember(){
        System.out.println(this.getClass().getSimpleName() + " can remember for 16 hours");
    }
    public void protectOwner(){
        System.out.println(this.getClass().getSimpleName()+ " won't protect owner");
    }
    public void climb(){
        System.out.println(this.getClass().getSimpleName()+ " can climb");
    }
}
interface Climb{
    void climb();
}
interface Think {
    void think();
}

interface Learn {
    void learn();
}
interface Apply{
    void apply();
}

class Man implements Think,Learn,Apply,Climb{
    String name;
    int age;

    public Man(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void think(){
        System.out.println("I can think:"+this.getClass().getSimpleName());
    }
    public void learn(){
        System.out.println("I can learn:"+this.getClass().getSimpleName());
    }
    public void apply(){
        System.out.println("I can apply:"+this.getClass().getSimpleName());
    }
    public void climb(){
        System.out.println("I can climb:"+this.getClass().getSimpleName());
    }
    public String toString(){
        return "Man :"+name+":Age:"+age;
    }
}

輸出:

Dog:Dog:Jack:16
Cat:Cat:Joe:20
Dog can remember for 5 minutes
Dog will protect owner
Dog can learn:
Cat can remember for 16 hours
Cat won't protect owner
Cat can climb
Man :Ravindra:Age:40
I can climb:Man
I can think:Man
I can learn:Man
I can apply:Man

主要說明:

  1. Animal 是一個具有共享屬性的抽象類:namelifeExpectancy 以及抽象方法:remember()protectOwner()DogCatAnimals,已經實現了 remember()protectOwner() 方法。

  2. Cat 可以 climb()Dog 不能。Dog 可以 think() 但是 Cat 不能。通過實現將這些特定功能新增到 CatDog

  3. Man 不是 Animal 但他可以 ThinkLearnApplyClimb

  4. Cat 不是 Man 但它可以 Climb

  5. Dog 不是 Man 但它可以 Learn

  6. Man 既不是 Cat 也不是 Dog 但是可以​​擁有後兩者的一些能力而不延伸 AnimalCatDog。這是通過介面完成的。

  7. 即使 Animal 是一個抽象類,它也有一個建構函式,與介面不同。

TL; DR:

不相關的類可以通過介面具有功能,但相關的類通過擴充套件基類來改變行為。

請參閱 Java 文件頁面以瞭解在特定用例中使用哪一個。

**** 如果…… 考慮使用抽象類

  1. 你希望在幾個密切相關的類之間共享程式碼。
  2. 你希望擴充套件抽象類的類具有許多常用方法或欄位,或者需要除公共之外的訪問修飾符(例如 protected 和 private)。
  3. 你想宣告非靜態或非最終欄位。

**考慮使用介面,**如果……

  1. 你希望不相關的類將實現你的介面。例如,許多不相關的物件可以實現 Serializable 介面。
  2. 你希望指定特定資料型別的行為,但不關心誰實現其行為。
  3. 你希望利用型別的多重繼承。