抽象类和抽象方法
用关键字abstract修饰的类称为abstract类(抽象类)。
用关键字abstract修饰的方法称为abstract方法(抽象方法)。
定义
- 一般情况下,类是用来实例化对象的。但在某些情况下,定义一些从未实例化对象的类是有意义的。这样的类就是抽象类。
- 抽象类把多种事物(类),也就是多个类的共性的内容抽取出来,可以只表示相同的相关功能,而不给出具体的实现。
- 抽象类的目的是提供一个合适的超类,以派生其他类。抽象类作为继承层次结构中的超类,又被称为抽象超类。
特点
抽象类有如下特点
- 对于抽象类,不能直接实例化对象,即不能使用new运算符创建该类的对象,只能先创建其子类,由子类创建对象。
- 抽象类可以声明对象,作为子类对象的上转型对象。
- 和普通的类相比,抽象类里可以有抽象方法,也可以没有抽象方法。
抽象方法有如下特点
- 对于abstract方法,只允许声明,不允许实现,也就是只定义相应的方法头,而没有体内容。
- 抽象方法不允许使用static、final修饰。
- 抽象类里面可以有抽象方法,也可以没有没有抽象方法,但含有抽象方法的类一定是抽象类。
- 抽象超类的所有具体子类都必须为超类的抽象方法提供具体实现,即实现抽象超类的所有抽象方法。在这儿说的具体子类就是不是抽象类的一般类。
- 抽象类的子类也可以是抽象类,子类是抽象类时不必实现抽象超类的所有抽象方法。
代码示例
代码:
public abstract class Score{ //抽象类
String subject;
double score;
Score(){}
Score(String subject,double score){ //构造函数
this.subject=subject;
this.score=score;
}
public String getSubject() { //get, set函数,非抽象方法
return subject;
}
public double getScore() {
return score;
}
public void setSubject(String subject) {
this.subject = subject;
}
public void setScore(double score) {
this.score = score;
}
abstract void print(); //抽象方法
}
class English extends Score{ //具体子类
English(double score){ //子类的构造函数
super("English", score); //调用父类的构造函数
}
void print(){ //实现父类中的抽象方法
System.out.println(subject+":"+score);
}
public static void main(String[] args) {
English score = new English(71.6);
score.print();
}
}
运行结果:
English:71.6
Process finished with exit code 0
接口
定义
Java使用关键字interface来定义一个接口。接口的定义和类的定义相似,分为接口的声明和接口体。
- 接口的声明格式:interface 接口的名字
- 接口体:接口体中包含常量定义和抽象方法定义两部分
定义接口的一般格式如下:
[public] interface 接口名 [extends 父接口名]{
[public] [static] [final] 数据类型 常量名=常量值;//常量声明
[public] [abstract] 返回类型 方法名(参数列表);//抽象方法声明
}
特点
- 接口可以抽象出重要的行为标准,该行为标准用抽象方法来表示。接口中只有常量和抽象方法。
- 接口中的变量自动都是 public static final,可以省略。
- 接口中的方法自动为 public abstract,可以省略。
- 接口编译后也产生class文件。
- 接口中没有构造方法,也就不能通过new构建接口的对象,只能像抽象类一样标示数据类型。
- 接口也具有继承性,可以继承父接口的所有属性和方法。
实现接口
- 接口中抽象的方法在某类中定义为具体方法。
- 一个类通过使用关键字implements声明自己实现一个或多个接口。
- 如果实现接口的类不是抽象类,那么这个类必须实现该接口的所有方法。
接口回调
接口回调是指:可以把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量中,那么该接口变量就可以调用被类重写的接口方法。实际上,当接口变量调用被类重写的接口方法时,就是通知相应的对象调用这个方法。
代码示例
代码:
interface Information{ //接口默认为public
String s = "Hello"; //接口中的变量默认为public static final,所以声明变量时要给出具体内容
void printInformation(); //接口中的方法默认为public abstract
}
class Car implements Information{ //具体类实现接口,多个接口用","分隔
@Override
public void printInformation() {
System.out.println(s+", "+"I'm a Car class.");
}
public void print() {
System.out.println(s);
}
}
class People implements Information{ //另一个具体类实现接口
@Override
public void printInformation() {
System.out.println(s+", "+"I'm a People class.");
}
}
class Test{
public static void main(String[] args) {
Information c; //变量c为Information类型
c=new Car(); //接口回调,将实现接口的类创建的对象的引用赋给该接口声明的接口变量
c.printInformation();
((Car) c).print(); //接口变量只能调用具体类中实现的接口方法,对于其他方法,需要强制类型转换
c=new People(); //接口回调
c.printInformation();
}
}
运行结果:
Hello, I'm a Car class.
Hello
Hello, I'm a People class.
Process finished with exit code 0
抽象类和接口总结
- 抽象类和接口组成不同,抽象类可以有变量、常量、构造方法、普通方法和抽象方法;接口只能有常量和抽象方法。
- 抽象类和接口都可以有抽象方法,但接口中方法只能是抽象方法。
- 抽象方法把“做什么” 和“怎么做” 分离,虽然代码量增加,但增强了程序的可维护性。
- 抽象类和接口的使用方式不同,抽象类通过子类继承,接口通过子类实现。
- 抽象类和接口都可以通过对象的多态性产生实例对象。
- 抽象类和接口在使用时,抽象类更像一个模板,接口一般作为标准或表示一种能力。
- 多使用面向接口编程或面向抽象编程 。