最近学习android开发,开始补习java的相关知识,从C++到java,让我经历了一段时间的痛苦期。下面谈谈我对接口与抽象类的理解
1. 语法上的不同
接口与抽象类在语法上就有着明显的区别:
(1) 成员变量
接口没有变量,在接口中定义的成员都是公共常量即public、final、static,即使不显示标识,编译器也会自动加上。
抽象类的成员变量完全依据显示定义的不同而不同,编译器不会做任何的动作去强行限制。
(2) 方法
接口的方法都隐含为public和abstract;接口中不能有非抽象的方法,并且方法不能是static、final、以及protected和private。
抽象类可以有非抽象的方法和抽象方法,但只要有一个方法是抽象的,则该类必须为抽象类,抽象方法不能为final、static、private。
(3) 继承
接口可以继承接口,但不能继承类,不能设计父接口的方法,不能实现其他接口。
抽象类只能继承一个父类,可以实现多个接口,可以选择性的设计父类或父接口中的抽象方法。
(4) 多态
接口类型的引用可以指向实现自该接口或实现自该接口的子接口的类,通过接口引用可以访问其指向的对象中,实现自接口的方法。
抽象类的引用可以指向其子类的对象,通过该引用可以访问子类中继承自该抽象类的所有属性和方法。
2. 具体含义的不同
抽象类更注重其实什么及其本质;而接口更注重其具有什么样的功能及其能充当什么样的角色。接口的实现与抽象类的继承其含义是不同的,开发人员应该站在不同的角度看待这个两个概念,抽象类物体的本质,而接口则是看待物体可以充当的角色。
习惯于使用C++的虚函数,其实C++的虚基类扮演了Java中的抽象类与接口两个角色。
//飞行器接口
public interface Flyer
{
// 具有飞行的功能
public void fly();
}
// 水上航行器接口
public interface Sailer
{
// 具有水上航行的功能
public void cruise();
}
// 机器抽象类
public abstract class Vehicle
{
public abstract void consume();
}
// 动物抽象类
public abstract class Animal
{
public abstract void eat();
}
// 飞机抽象类
public abstract class AirPlane extends Vehicle implements Flyer
{
@Override
public void consume()
{
System.out.println("我需要消耗汽油!");
}
@Override
public void fly()
{
System.out.println("我可以用飞机的方式在天空飞!");
}
}
//飞机类
public class SeaPlane extends AirPlane implements Sailer
{
@Override
public void cruise()
{
System.out.println("我可以用船的方式在水中航行!");
}
}
//鸟类
public class Brid extends Animal implements Flyer
{
@Override
public void eat()
{
System.out.println("我需要吃东西!");
}
public void fly()
{
System.out.println("我可以用动物的方式在天空飞!");
}
}
public class Example
{
public static void main(String[] args)
{
SeaPlane sp = new SeaPlane();
Brid b = new Brid();
System.out.println("======水上飞机执行的动作======");
sp.fly();
sp.consume();
sp.cruise();
System.out.println("======鸟执行的动作======");
b.fly();
b.eat();
}
}
从例子可以看出,水上飞机与鸟都会飞,都实现了飞行器接口。但水上飞机与鸟有本质的区别,他们没有任何继承关系。同时,水上飞机还可以充当水上航行器的角色。
打印结果:
======水上飞机执行的动作======
我可以用飞机的方式在天空飞!
我需要消耗汽油!
我可以用船的方式在水中航行!
======鸟执行的动作======
我可以用动物的方式在天空飞!
我需要吃东西!