抽象类和接口用法 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
接口。 - 你希望指定特定数据类型的行为,但不关心谁实现其行为。
- 你希望利用类型的多重继承。