0.前言
在C++中,一个类可以继承许多类,我们称之为多继承,但是在java中这是不被允许的。也许你看到过一句话:我们可以使用接口来达成多继承。我们暂且将这个问题置于一边,先看看C++中如何实现接口。
1.C++中的接口
接口描述了一个类的特征和行为,但是却不需要具体实现,很自然的可以联想到抽象类来实现。试考虑以下代码:
class Geography
{
public:
Geography():area(0),circum(0){};
double GetArea(){
return area;
}
void SetArea(double a)
{
area=a;
}
virtual void CalculateArea()=0;
private:
double area;
double circum;
};
我们定义了一个抽象类,数据域中的area是不开放的,我们给了两个函数来对它访问,同时定义了一个虚函数,下面是它的一个实现。
class Circle:public Geography
{
public:
Circle(double r):Geography(),radius(r)
{
CalculateArea();
};
void CalculateArea()
{
SetArea(radius*radius*3.1416);
}
private:
double radius;
};
在C++中抽象类和接口没有分开,但我们能隐隐感受到两者区别,类有很强的is-a关系,但是接口只是描述了一方面通用的属性。
2.Java中的接口
先看看如何像C++那样子实现我们想要的。
abstract class Animal{
public abstract String howToEat();
}
class Chicken extends Animal{
@Override
public String howToEat() {
return "Fry it";
}
}
class Duck extends Animal{
@Override
public String howToEat(){
return "Roast it";
}
}
public class Main {
public static void main(String[] args) {
Animal animal=new Chicken();
eat(animal);
animal = new Duck();
eat(animal);
}
public static void eat(Animal a)
{
System.out.println(a.howToEat());
}
}
但是从设计角度来考虑,难道只有动物是可以吃的吗?我们也会吃蔬菜水果零食等等,而且进一步思考,怎么被吃似乎不是一个动物的方法吧,将它归为所有动物都有的似乎不太合适,下面是接口是如何实现的。
interface Edible{
public abstract String howToEat();
}
class Chicken implements Edible{
@Override
public String howToEat() {
return "Fry it";
}
}
class Duck implements Edible{
@Override
public String howToEat(){
return "Roast it";
}
}
class Watermelon implements Edible{
@Override
public String howToEat(){
return "just eat it";
}
}
public class Main {
public static void main(String[] args) {
Edible food = new Chicken();
eat(food);
food = new Watermelon();
eat(food);
}
public static void eat(Edible a)
{
System.out.println(a.howToEat());
}
}
3.总结
接口为抽象提供了一种更加合理的选择。接口更加像是一种……协议?我们规定了接口就代表这些类需要达成这些才是合格的。
总结一下抽象类和接口的区别,以下内容摘自知乎:
1)语法层面上
- 接口中不能有 public 和 protected 修饰的方法,抽象类中可以有。
- 接口中的变量只能是隐式的常量,抽象类中可以有任意类型的变量。
- 一个类只能继承一个抽象类,但却可以实现多个接口。
2)设计层面上
抽象类是对类的一种抽象,继承抽象类的类和抽象类本身是一种 is-a
的关系。
接口是对类的某种行为的一种抽象,接口和类之间并没有很强的关联关系,所有的类都可以实现 Serializable
接口,从而具有序列化的功能。
[…] 算一算很长时间没有写过文章了。不过隔壁出了个Java的抽象类与接口,那我当然很有兴趣来写写C#的抽象类和接口啦。本文意在于介绍抽象类以及接口的配合使用,关于更多细节请参考微软官方文档。 […]