1 抽象类
类的继承中,子类拥有父类的所有属性和方法,父类的某些方法实现在子类 中可能不够全面,而要求在子类中重写,这时父类经常设计为抽象类,抽象类的某些方法只有声明没有实现。子类除了继承父类的属性和方法外,每个类还包含很多其他的功能(也就是方法),这时经常把功能方法抽象为接口,接口中只声 明方法,要求具体的类实现该方法。
Java 中每一个类只能有一个父类(包括抽象类),但是可以同时实现多个接口。
Abstract 修饰符只能修饰类和普通的方法。用 abstract 关键字修饰的类就是抽象类,用 abstract 修饰的方法叫做抽象方法。在抽象类中允许方法不进行具体的实现。抽象方法不是一个完整的方法,只做方法的声明,没有方法体。
1.1 抽象类的作用
抽象类是为了实现多态,并优化继承结构。
例如:抽象类
/*宠物的抽象类 */
public abstract class Pet {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Pet(String name) {
super();
this.name = name;
}
//抽象方法
public abstract void eat();
}
子类
public class Pig extends Pet{
public Pig(String name) {
super(name);
}
//实现父类的方法
@Override
public void eat() {
System.out.println("小猪在吃草");
}
}
1.2 注意
抽象类可能只提供一个类的部分实现,因此抽象类不能被实例化,抽象类可以有成员变量(成员变量也叫实例变量),以及一个或多个构造方法,这些构造方法不能被客户端调用来创建实例,抽象类的构造方法可以被子类用 super 来调用。
抽象类可以同时拥有抽象方法和具体方法,抽象类使所有的子类都可以有一 些共同的实现,而不同的子类可以在此基础上对抽象方法做具体的实现。
(1)抽象方法只能定义在抽象类中。
(2)抽象类中不一定有抽象的方法。
(3)抽象类中可以有具体的方法和自己的私有属性。
(4)抽象类不可以被实例化(不能创建对象),它是专门用来被继承的。
(5)当一个类继承一个抽象类,该类必须实现抽象类中的抽象方法(前提条件: 抽象类中有抽象方法)。
(6)抽象方法不可以被 final 修饰。抽象类也不可以被 final 修饰。
1.3 抽象类的设计原则
抽象类是用来继承的,只要有可能,不要从具体类继承。假设有 2 个具体类, 类 A 和类 B,类 B 是类 A 的子类,那么一个最简单的修改方案是应当建立一个抽 象类 C(或者接口),然后让类 A 和类 B 分别去继承抽象类 C。
抽象类应当拥有尽可能多的共同代码,以提高代码的复用率。
2 接口
接口就是规定了一系列的规则、标准、动作等,不做具体的实现。就像电脑 硬件中的 PCI 插槽。一个类中如果不存在数据,只存在抽象方法时,就可以声明 为接口,定义接口使用的关键字不是 class,而用 interface 来声明。
2.1 接口的特点
(1)在接口中的所有方法都默认是 public abstract 修饰的。
(2)在接口中定义的属性默认为 public final 修饰。(一般情况接口中是不建议 定义属性的)。对于接口当中常见的成员,而且这些成员都有固定的修饰符,例如:全局常量用 public static final 修饰,抽象方法用 public abstract 修饰。 由此得出结论,接口中的成员都是公共的权限。
(3)在接口中只能有抽象的方法,不能有具体的方法。
(4)在接口中的属性和方法都 不能使用 private 修饰 。
(5)接口不可以实例化,只能由实现了接口的子类并覆盖了接口中所有的抽象 方法后,该子类才可以实例化,否则,这个子类就是一个抽象类。
(6)接口与类是并列的概念,类与类之间是继承关系,类与接口之间是实现关系。实现接口使用关键字 implements 。
(7)在 java 中 不直接支持多继承 ,因为会出现调用的不确定性。所以 java 将 多继承机制进行改良,在 java 中变成了多实现。一个类可以实现多个接口。实现多个接口时,接口之间用逗号分隔。
(8)一个类在继承另一个类的同时,还可以实现多个接口。
(9)接口是不能够实现接口, 接口与接口之间是继承关系,并且是多继承 。(虽 然用的不多,但存在)。但是类与类之间只能是单继承,原理就在于方法体是否有实现。
2.2 接口和抽象类的异同
相同点:都是不断向上抽取而来的。
不同点:
(1)抽象类定义的时候使用 abstract class,接口使用 interface 定义。
(2)抽象类中可以有自己私有的属性,但是接口中不能有私有的属性,接口中的属性默认都是 public final 修饰。
(3)抽象类中可以有具体的方法,还可以没有抽象方法,但是接口中不能有具体的方法,必须都是抽象的方法。
(4)抽象类只能单继承,但是接口可以多继承。
(5)抽象类可以实现接口,但是接口不能够实现接口。
(6)在一般情况下,在使用继承的时候,优先考虑接口,再考虑抽象类。
(7)接口主要针对的是行为特性。抽象类侧重点还是类。
(8)抽象类的继承,是 is a 关系,在定义该体系的基本共性内容。接口的实现是 like a 关系,在定义体系额外功能。
二者关系: 抽象类可以实现接口,但是在抽象类中可以不对接口中的方法进行具体实 现,如果不在抽象类中实现,则将方法的实现交给子类。
2.3 抽象类和接口的好处
(1)重要性:在 Java 语言中, abstract class 和 interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了 Java 强大的面向对象能力。
(2)简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无 法看明白)。
(3)维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。 可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这 个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起 来很麻烦。如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时 实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。 (4)安全、严密性:接口是实现软件松耦合的重要手段,它描述了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。