抽象類和介面用法 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
主要說明:
-
Animal
是一個具有共享屬性的抽象類:name
和lifeExpectancy
以及抽象方法:remember()
和protectOwner()
。Dog
和Cat
是Animals
,已經實現了remember()
和protectOwner()
方法。 -
Cat
可以climb()
但Dog
不能。Dog
可以think()
但是Cat
不能。通過實現將這些特定功能新增到Cat
和Dog
。 -
Man
不是Animal
但他可以Think
,Learn
,Apply
和Climb
。 -
Cat
不是Man
但它可以Climb
。 -
Dog
不是Man
但它可以Learn
-
Man
既不是Cat
也不是Dog
但是可以擁有後兩者的一些能力而不延伸Animal
,Cat
或Dog
。這是通過介面完成的。 -
即使
Animal
是一個抽象類,它也有一個建構函式,與介面不同。
TL; DR:
不相關的類可以通過介面具有功能,但相關的類通過擴充套件基類來改變行為。
請參閱 Java 文件頁面以瞭解在特定用例中使用哪一個。
**** 如果…… 考慮使用抽象類
- 你希望在幾個密切相關的類之間共享程式碼。
- 你希望擴充套件抽象類的類具有許多常用方法或欄位,或者需要除公共之外的訪問修飾符(例如 protected 和 private)。
- 你想宣告非靜態或非最終欄位。
**考慮使用介面,**如果……
- 你希望不相關的類將實現你的介面。例如,許多不相關的物件可以實現
Serializable
介面。 - 你希望指定特定資料型別的行為,但不關心誰實現其行為。
- 你希望利用型別的多重繼承。