抽象类
抽象类的结构:
- 抽象类都是用abstract关键字修饰的类,不能被实例化即——不能用new关键字直接创建实例对象(即使抽象类中不包含抽象方法也不行)。
- abstract关键字放在class之前。
- 一个抽象类中可以含有多个抽象类,也可以含有已实现的方法。
- 抽象类可以含有构造方法和成员变量,但是不能通过构造方法创建实例,可在子类创建实例时调用。
- abstract不能与native、final、static等关键字同时使用。
定义抽象类的三种情况:
- 直接定义一个抽象类。
- 继承一个抽象类,但没有完全实现父类的所有抽象方法。
- 实现一个抽象接口,但没有完全实现接口中包含的抽象方法。
抽象方法
抽象方法的结构
- abstract关键字放在方法的返回类型前。
- 抽象方法没有方法体。
- 必须被子类重写才有意义,否者这个方法永远不会有方法体,所以修饰符不能是private。
- 抽象方法要被实现,所以不能是静态的,也不能是私有的。
抽象类代码演示:
父类Animal:
package com.qst.hgl.absracttest;
public abstract class Animal { // 抽象类
private String name;
public Animal() {
} // 空构造方法
public Animal(String name) {
this.name = name; // 初始化实例的构造方法
}
public abstract void Action();// 抽象方法
public abstract void Eating();// 抽象方法
public String getName() { // 普通成员方法
return name;
}
public void setName(String name) { // 普通成员方法
this.name = name;
}
}
子类Bird:
package com.qst.hgl.absracttest;
public class Bird extends Animal {
public Bird() {
} // 空构造方法
public Bird(String name) {
super(name);
}
public void Action() {
System.out.println(this.getName() + "在天空中飞翔!");// 重写父类抽象方法
}
public void Eating() {
System.out.println(this.getName() + "在树梢上吃虫子");// 重写父类抽象方法
}
}
子类Horse:
package com.qst.hgl.absracttest;
public class Horse extends Animal {
public Horse() {
} // 空构造方法
public Horse(String name) {
super(name); // 调用父类的构造方法
}
public void Action() {
System.out.println(this.getName() + "在地上奔跑!");// 重写父类抽象方法
}
public void Eating() {
System.out.println(this.getName() + "在山上啃地皮");// 重写父类抽象方法
}
}
测试类AnimalDemo:
package com.qst.hgl.absracttest;
public class AnimalDemo {
public static void main(String[] args) {
Animal a; // 新建一个实例a
a = new Horse("汗血宝马"); // 如果a是马
a.Action();
a.Eating();
a = new Bird("不死凤凰"); // 如果a是鸟
a.Action();
a.Eating();
}
}
运行结果:
接口
Java的继承机制是单继承,不支持多继承,但是这一缺陷却可以通过接口来弥补,因为一个类可以继承多个接口。
Java的继承机制是单继承,不支持多继承,但是这一缺陷却可以通过借口来弥补,因为一个类可以继承多个接口,使用接口可以让程序变得更灵活、易扩展。
接口的语法结构:
- 语法:
[访问控制符] interface 接口名[extends 父接口1,父接口2]{
//接口体
}
- 一个借口可以继承多个父接口,但接口只能继承接口,不能继承类。
- 接口体可以包含静态常量、抽象方法、内部类、内部接口以及枚举的定义,从Java8版本开始支持在接口中定义默认方法、类方法。
- 系统会自动为接口中的方法添加public abstract进行修饰。
- 不能对接口直接实例化
//错误示例:
MyInterface m=new MyInterface();
- 可以声明接口变量,并用接口变量指向当前接口实现类的实例,这也是多态性的一种体现
//比如:
MyInterface m=new ImInterfaceDemo();
- 接口继承与类继承有些不一样,接口继承完全支持多继承,接口继承可以拥有多个父接口。其他方面二者相差不大。
- 实现了接口的类,必须实现接口的方法以及接口继承的父接口的方法
抽象类和接口的区别:
- 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
- 抽象类要被子类继承,接口要被类实现。
- 接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
- 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
- 抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
- 抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果
- 抽象类里可以没有抽象方法
- 如果一个类里有抽象方法,那么这个类只能是抽象类
- 接口可继承接口,并可多继承接口,但类只能单根继承。
- 抽象类 和 接口 都是用来抽象具体对象的. 但是接口的抽象级别最高
- 抽象类可以有具体的方法 和属性, 接口只能有抽象方法和不可变常量
- 抽象类主要用来抽象类别,接口主要用来抽象功能.
- 抽象类中,可有构造函数且不包含任何实现,但是派生类必须覆盖它们。接口中所有方法都必须是未实现的。