抽象类和方法

之前基于继承的多态,可以看出来父类并没有被实例化,而且成员方法也可以没有实体也就是函数体,只需要父类类型引用指向各个子类对象,通过子类方法的覆盖就可以达到调用方法的目的,回头看下之前的例子,父类Book有三种各异的方法,又是chinese,又是english和maths,如果从属性的角度考虑,这到底是本神马书?因此一般来说,这个父类用来被继承和产生多态,可以避免让它进行初始化,也就是没法new出来,既然没法实例化,就相当于标记成了一个抽象的类,无法创建任何类型的实例,但是却依旧可以创建抽象类类型的引用变量来进行多态调用

抽象类的标记十分简单,在声明前面加一个关键字abstrace即可,比如进行实例化编译就会报错

abstract class Book {
    void chinese() {};
}

class ChineseBook extends Book {
    void chinese() {
        System.out.println("A chinese book");
    }
}

public class Main {
    public static void main(String[] args) {
        Book book = new Book();
        book.chinese();
    }
}

这里Book类进行抽象化,编译出错

javac Main.java
Main.java:13: 错误: Book是抽象的; 无法实例化
        Book book = new Book();
                    ^
1 个错误

换成父类引用指向的子类对象初始化进行多态,即可

abstract class Book {
    void chinese() {};
}

class ChineseBook extends Book {
    void chinese() {
        System.out.println("A chinese book");
    }
}

public class Main {
    public static void main(String[] args) {
        Book book = new ChineseBook();
        book.chinese();
    }
}

既然abstract的类,被抽象化,无法实例化,那这个类肯定被extends过;同样方法也可以添加关键字abstract来进行抽象化,但是要注意的是,如果声明了一个抽象的方法,就必须将其类也标记为抽象类,不能再非抽象类中定义抽象方法

抽象的方法定义

abstract class Book {
    abstract void chinese();
}

要注意的是抽象的方法不用带任何函数体,带了编译会报错

抽象方法的多态程序

abstract class Book {
    abstract void chinese();
}

class ChineseBook extends Book {
    void chinese() {
        System.out.println("A chinese book");
    }
}

public class Main {
    public static void main(String[] args) {
        Book book = new ChineseBook();
        book.chinese();
    }
}

由此来看,并不影响子类覆盖方法的多态行为,下面再看一个

给父类加了一个正常的成员方法

abstract class Book {
    abstract void chinese();
    void english() {};
}

class ChineseBook extends Book {
    void chinese() {
        System.out.println("A chinese book");
    }
}

public class Main {
    public static void main(String[] args) {
        Book book = new ChineseBook();
        book.chinese();
    }
}

这里是没有问题的,子类的chinese()重写了父类对应的方法,最后book调用的方法还是执行的子类里的方法输出

假如这里将父类里的english方法改成抽象方法

abstract class Book {
    abstract void chinese();
    abstract void english();
}

class ChineseBook extends Book {
    void chinese() {
        System.out.println("A chinese book");
    }
}

public class Main {
    public static void main(String[] args) {
        Book book = new ChineseBook();
        book.chinese();
    }
}

编译就会出错

javac Main.java
Main.java:6: 错误: ChineseBook不是抽象的, 并且未覆盖Book中的抽象方法english()
class ChineseBook extends Book {
^
1 个错误

可以看到错误信息居然是ChineseBook不是抽象类,理清一下脉络,english不是抽象方法,但ChineseBook继承了Book,于是也继承了Book的所有方法,而这里都是抽象方法,于是乎ChineseBook有了抽象成员方法,那么ChineseBook必须也声明为抽象类才行,这显然不满足后面的实例化要求,于是必须在子类里将english方法也进行覆盖即可

abstract class Book {
    abstract void chinese();
    abstract void english();
}

class ChineseBook extends Book {
    void chinese() {
        System.out.println("A chinese book");
    }
    void english() {
        System.out.println("A english book");
    }
}

public class Main {
    public static void main(String[] args) {
        Book book = new ChineseBook();
        book.chinese();
    }
}

通过上面的几个例子,基本可以将抽象类和方法的要求理清了:

1:抽象类无法实例化,无法用new创建对象

2:抽象方法没有函数主体

3:抽象类里可以包括非抽象方法

4:只要类中有抽象方法,那么这个类必须声明为抽象类

5:抽象类的子类中必须覆盖掉父类所有的抽象方法

发表评论