抽象類和介面用法 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 是一個具有共享屬性的抽象類:name 和 lifeExpectancy 以及抽象方法:remember() 和 protectOwner()。Dog 和 Cat 是 Animals,已經實現了 remember() 和 protectOwner() 方法。

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

  3. Man 不是 Animal 但他可以 Think,Learn,Apply 和 Climb。

  4. Cat 不是 Man 但它可以 Climb。

  5. Dog 不是 Man 但它可以 Learn

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

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

TL; DR:

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

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

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

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

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

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