一个类型的实现可以通过抽象类与接口实现两种方式,这两种机制的区别主要区别在于,抽象类允许包含某些方法的实现,但是接口不允许。实现抽象类就必须成为抽象类的一个子类,但是Java的单继承模式会给子类造成极大的约束。因此说接口优先于抽象类。
一:抽象类
当编写一个类,其定义的一些行为方式无法准确的描述,也就是说某一个父类只知道其子类应该包含怎样的方法,但无法准确的知道子类的实现方式。这个时候我们可以将这些方法进行抽象,将这些方法加入abstract关键字,使这些方法变为抽象方法(抽象方法是只有方法名而不提供具体实现的方法)。有抽象方法的类称为抽象类,但一个抽象类中可以没有抽象方法。抽象方法和抽象类的规则如下:
a:抽象类和抽象方法必须使用abstract进行修饰,抽象方法不能有方法体;
b:抽象类无法实例化,也就是说无法使用new关键字来构造实例,即便是抽象类中没有抽象方法;
c:抽象类中的构造器不能用于创建实例,用于子类的调用;
d:abstract修饰的抽象方法必须被子类重写才有意义,因此抽象方法不能定义为private访问权限,不能让private与abstract同时修饰方法。
e:含有抽象方法、继承抽象父类但没有完全实现抽象方法、实现了一个接口却没有完全实现接口包含的所有抽象方法,这三种情况下的类是抽象类;
抽象类是从多个具体类中抽象出的父类,具有更高层次的抽象。从共同特征中抽象出一个抽象类,将这个抽象类作为基点,约束子类的设计。抽象类体现的是一种与C++模板相似的设计思想,子类在模板上进行拓展与实现。这种模板设计模式是常见的设计模式。例如Shape,Circle,Rectangle的关系,我们在Shape进行抽象,Circle类、Rectangle类进行实现,可以这样定义:
abstract class shape{
//计算图形周长
public abstract double calPerimeter();
//计算图形面积
public abstract double area();
}
//circle类
class cirlce extends shape
{
private double r;
public cirlce(double r) {
super();
this.r = r;
}
@Override
public double calPerimeter() {
return 2*r*Math.PI;
}
@Override
public double area() {
return r*r*Math.PI;
}
}
//rectangle类
class rectangle extends shape
{
private double length;
private double high;
public rectangle(double length, double high) {
super();
this.length = length;
this.high = high;
}
@Override
public double calPerimeter() {
return (length + high ) * 2;
}
@Override
public double area() {
return length * high ;
}
}
public class Graph {
public static void main(String[] args) {
shape s1 = new cirlce(3);
shape s2 = new rectangle(4,5);
System.out.println("圆形的面积是:"+s1.area()+" 周长是:"+s1.calPerimeter());
System.out.println("矩形的面积是:"+s2.area()+" 周长是:"+s2.calPerimeter());
}
}
由此可见抽象父类可以定义需要使用的某些方法,把不能实现的方法抽象成抽象方法,令子类实现。 二:接口 接口是一种更加彻底的抽象,接口中不能包含普通方法,只有抽象方法。接口是从多个相似类中抽象出来的规范,接口不提供任何实现,体现的是设计与实现分离的哲学。 接口定义的是多个类的公共行为规范,这些行为是外部交流的通道,也就是说接口中是公用方法。定义接口要采用interface关键字,虽然说Java不允许类的多继承,但是接口之间存在多继承,类也可以实现多个接口,接口支部包含构造器和初始化快的定义。。由于接口是一种规范,因此说接口不应该经常改变,接口的改变对其他类的影响很大。 接口中允许有常量、方法、内部类的定义。对于接口内的常量,由于它们是接口相关,系统会自动为它们添加static与final关键字进行修饰,也就是说接口内的常量只能在定义时指定默认值。同一个Java源文件中只允许有一个public接口,如果一个源文件中有一个public接口,文件名必须与接口名一致,接口是特殊的类。实现接口与继承父类相似,实现接口需要在类定义后添加implements关键字。多个关键字之间通过“,"进行间隔,implements必须放在extends部分之后。 充分利用接口可以降低程序的耦合度,提高程序的可维护性和拓展性,要面向接口编程,例如常见的简单工厂模式,可以这样定义:
<span style="font-size:14px;">interface IProduct {
void doSomeThing();
}
class ProductA implements IProduct {
public void doSomeThing() {
}
}
class ProductB implements IProduct {
public void doSomeThing() {
}
}
class Creator {
public static IProduct factory(String product){
if(product.equals("a"))
return new ProductA();
else if(product.equals("b"))
return new ProductB();
}
}</span>