1 抽象类
1.1 抽象类的基本概念
如果说现在在一个类之中需要定义一个没有方法体的一个方法,那么可以利用abstract关键字来进行抽象方法的定义,而包含有抽象方法的类就可以使用abstract来定义成为抽象类。
假如说有一个A类在设计之初有一个要求,希望继承他的子类一定要覆写他的方法。但事实上,这个时候的子类完全可以灵活的选择是否覆写方法。但是由于只是一个普通方法,所以对于子类是否覆写没有任何的要求,于是这样就会出现一个漏洞,父类无法强制要求子类覆写方法。
如果只依靠普通类的继承,那么根本就不能对子类产生限制,所以就可以利用抽象类和抽象方法来解决此类问题。
抽象类无法实例化。(即使没有抽象方法)
抽象类的子类(如果不是抽象类),那么必须要覆写抽象类中的全部抽象方法。
抽象类可以利用对象的向上转型机制,通过子类对象进行实例化操作。
抽象类不能使用final关键字来定义,因为抽象类必须有子类,而final不能子类。
外部抽象类上不允许使用static声明,但是内部抽象类中可以使用static声明,这样表明的是一个外部抽象类。
abstract class A{
public abstract void printA();
static abstract class B{
public abstract void printB();
}
}
class B extends A.B{
@Override
public void printB() {
}
}
抽象类中可以存在static方法,而且static方法不受实例化对象控制。
abstract class A{//此类实际之初考虑以后发展需要有子类
public abstract void printA();
private static class B extends A{//在A类里面直接定义实现子类
public void printA(){
System.out.println("Hello World");
}
}
public static A getInstance(){
return new B();
}
}
public class AbstractDemo {
public static void main(String[] args) {
A a=A.getInstance();
a.printA();
}
}
抽象类就是比普通类多了抽象方法而已,但是普通类中的所有结构抽象类都可以定义,包括:普通方法,构造方法,属性,常量。而且子类对象也符合于对象实例化流程,默认先调用父类中的无参构造方法,而后在执行子类自己的构造操作。
abstract class A{
public static final String INFO="HELLO";//常量
public A(){
this.fun();
}
public void fun(){
System.out.println("***************");
}
public abstract void print();//没有方法体
}
class B extends A{
public void print(){
System.out.println("强制覆写的方法");
}
}
public class AbstractDemo {
public static void main(String[] args) {
A a=new B();//向上转型
a.print();
}
}
抽象类与普通类相比最大的好处就是强制定义了子类的实现要求。
本质上讲抽象类就是比普通类多了一些抽象方法的定义而已。
在实际的设计之中,父类的设计是最重要的,普通类与抽象类相比,明显抽象类的约束更加的严格,所以在实际的开发之中,几乎不会出现普通类定义子类的情况,大多数都是继承抽象类。
思考:
abstract class A{
public A(){//2 默认调用父类构造
this.print();// 3 调用PRINT()方法
}
public abstract void print();
}
class B extends A{
private int num=50;
public B(int num){//1 内容传递过来,在子类对象实例化之前先实例化父类对象
this.num=num;
}
public void print(){//4 调用此方法执行,但是此时子类对象还没有实例化
System.out.println(num);
}
}
public class AbstractDemo {
public static void main(String[] args) {
new B(100);// 结果 0
}
}
子类对象实例化之前一定要先实例化父类对象,也就是说此时,子类对象的属性都没有内容。
1.2 抽象类的实际应用-模板设计模式
abstract class Action{
public abstract void eat();
public abstract void sleep();
public abstract void work();
}
class People extends Action{
@Override
public void eat() {
System.out.println("人在吃饭");
}
@Override
public void sleep() {
System.out.println("人在休息");
}
@Override
public void work() {
System.out.println("人在工作");
}
}
class Robot extends Action{
@Override
public void eat() {
System.out.println("机器人在充电");
}
@Override
public void sleep() {
}
@Override
public void work() {
System.out.println("机器人在工作");
}
}
class Pig extends Action{
@Override
public void eat() {
System.out.println("猪在进食");
}
@Override
public void sleep() {
System.out.println("猪在睡觉");
}
@Override
public void work() {}
}
public class AbstractDemo {
public static void main(String[] args) {
fun(new Pig());
System.out.println("***************");
fun(new People());
System.out.println("***************");
fun(new Robot());
System.out.println("***************");
}
public static void fun(Action action){
action.eat();
action.sleep();
action.work();
}
}
现在在整个程序之中,如果某一类事物需要实现特定功能,那么就必须按照Action所定义的方法进行覆写。这个时候子类必须按照父类提供的
模板编写代码。