抽象类和接口用法 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. 你希望利用类型的多重继承。