抽象类
使用 abstract 关键字定义的类称为抽象类,而使用这个关键字定义的方法称为抽象方法。抽象方法没有方法体,这个方法本身没有任何意义,除非它被重写,而承载这个抽象方法的抽象类必须被继承,实际上抽象类除了被继承没有任何意义。定义抽象类的语法如下:
权限修饰符 abstract class 类名
abstract 返回值类型 方法名()
public abstract class Test{ //抽象类
abstract void testAbstract(); //抽象方法
}
反过来讲,如果声明一个抽象方法,就必须将承载这个抽象方法的类定义为抽象类,不能在非抽象类中获取抽象方法。换句话说,只要类中有一个抽象方法,此类就被标记位抽象类。
抽象类被继承后,需要实现其中所有的抽象方法,也就是使用同样的名称、参数列表和返回值类型创建出非抽象方法。
这样在多态机制中,就可以将父类修改为抽象类,将 draw() 方法设置为抽象方法,然后每个子类都重写这个方法来处理。但这又会出现代码重复、冗余的问题,同时这样的父类局限性很大,也许某个不需要 draw() 方法的子类的也不得不重写 draw() 方法。如果将 draw() 方法放置在另外一个类中,让那些需要 draw() 方法的类来继承该类,不需要 draw() 方法的类继承图形类,又会产生新的问题:所有的子类都需要继承图形类,因为这些类是从图形类中导出的,同时某些类还需要 draw() 方法,而 Java 中又规定类不能同时继承多个父类。为了应对这种问题,接口的概念便出现了。
接口
接口是抽象类的延伸,可以将它看做是纯粹的抽象类,接口中所有的方法都没有方法体。为了解决上面出现的问题,可以将 draw() 方法封装到一个接口中,使需要 draw() 方法的类实现这个接口,同时也继承图形类,这就是接口存在的必要性。
接口使用 interface 关键字进行定义,其语法如下:
权限修饰符 interface 接口名称
public interface Paintable{ //public 关键字仅限用于接口在与其同名的文件中被定义
void draw(); //定义接口方法可省略 public abstract 关键字
}
一个类继承一个父类的同时再实现一个接口,可以写成如下形式:
public class Parallelogram extends Quadrangle implements Paintable{
...
}
注意事项:
1.在接口中,方法必须被定义为 public 或 abstract 形式,其他修饰权限不被 Java 编译器认可。或者说,即使不将该方法声明为 public 形式,它也是 public 形式。
2.在接口中定义的任何字段都自动是 static 和 final 的。
将绘图方法设为接口方法,应用实例如下:
将图形对象的绘图方法剥离出来,作为 Paintable 可绘制接口中的抽象方法。创建四边形类作为平行四边形类和正方形类的父类,同时让这两个子类实现 Paintable 接口。创建圆形类实现 Paintable 接口,但不继承四边形类。
interface Paintable { // 可绘制接口
public void draw(); // 绘制抽象方法,省略了 public abstract 关键字
}
class Quadrangle { // 四边形类
public void doAnything() {
System.out.println("四边形提供的方法");
}
}
//平行四边形类,继承四边形类,并实现了可绘制接口
class Parallelogram extends Quadrangle implements Paintable {
public void draw() { // 由于该类实现了接口,所以需要重写draw()方法
System.out.println("绘制平行四边形");
}
}
//正方形类,继承四边形类,并实现了可绘制接口
class Square extends Quadrangle implements Paintable {
public void draw() { // 由于该类实现了接口,所以需要重写draw()方法
System.out.println("绘制正方形");
}
}
//圆形类,仅实现了可绘制接口
class Circular implements Paintable {
public void draw() {
System.out.println("绘制圆形");
}
}
public class Test {
public static void main(String[] args) {
Square s = new Square();
s.draw();
s.doAnything();
Parallelogram p = new Parallelogram();
p.draw();
p.doAnything();
Circular c = new Circular();
c.draw();
}
}
运行结果如下:
绘制正方形
四边形提供的方法
绘制平行四边形
四边形提供的方法
绘制圆形
从上述例子可以看出, draw() 方法被独立封装在了可绘制接口中。
Java 语法中不允许出现多重继承,但是使用接口后,可以实现多重继承。在上述实例中,正方形类和平行四边形类既继承了四边形类中的 doAnything() 的方法,又调用了接口中的 draw() 方法;而圆形对象只调用了接口中的 draw() 方法。一个类可以同时实现多个接口,因此可以将所有需要继承的接口放置在 implement 关键字后并使用逗号隔开。实现多个接口的语法如下:
class 类名 implements 接口1,接口2,接口3,...,接口n
但是这样写可能会在一个类中缠上庞大的代码量,因为继承一个接口时需要实现接口中所有的方法,这样不利于代码的扩展与维护。因此,一个接口可以继承另一个接口,其语法如下:
interface intf1{ }
interface intf2 extends intf1{ } //接口 intf2 继承接口 intf1
部分摘抄自 明日科技《Java从入门到精通》