java 抽象类

124 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

抽象类

抽象类的产生

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类

使用类是描述生活中的某一类事物,但是事物和事物之间又有继承的关系,因此我们描述的类和类之间也会有继承关系存在。

在继承中,越往顶层父类中,其中描述的属性和行为更加的共性。

我们在描述事物的过程中,把共性的行为或属性不停的往父类中抽取,这样就会导致在父类中描述的行为越来越不具体,无法表示出事物的特有的特点。可是这时我们依然要进行抽取和简单的描述。

描述猫和狗:

猫:

吃鱼

抓老鼠

狗:

啃骨头

看家

狗和猫中有共性的吃的行为,这时我们可以抽取到父类动物类中,但是在动物类中,这个吃的行为的行为体是没有办法写的十分清楚和具体。

这时我们就需要使用Java中的抽象的概念来描述这个无法写清楚的行为。由于行为我们在Java中以函数的形式体现,也就是说这个函数就变成一个抽象的函数,一旦某个类中有了抽象的函数这个类就变成抽象类了。

对上述描述的猫和狗使用java代码体现出来:

1)定义两个类Cat和Dog类;

2)在Cat类中定义两个函数eat和catchMouse;

3)在Dog类中定义两个函数eat和lookHome;

4)定义一个测试类测试Cat和Dog类;

class Dog 
{
    void eat()
    {
        System.out.println("啃骨头");
    }
    void lookHome()
    {
        System.out.println("看家");
    }
}
​
class Cat
{
    void eat()
    {
        System.out.println("吃鱼");
    }
    void catchMouse()
    {
        System.out.println("抓老鼠");
    }
}
​
class AbstractDemo 
{
    public static void main(String[] args) 
    {
        Cat c = new Cat();
        c.eat();
    }
}

通过分析:以上程序中存在共性的内容

Cat类和Dog类中共性内容:

在上述两个类中都有吃的行为,遇到共性内容,需要向上抽取,抽取存放到类中:把共性内容封装到Animal类中。

我们把狗和猫中的eat行为抽取到了Animal类中,但是我们没有办法去明确具体的函数体代码,如果没有办法明确具体的函数体的时候,这时可以把函数体省略。在java中没有函数体的函数我们称为抽象的函数,这个函数必须使用Java中的抽象关键字修饰。抽象关键字:abstract

什么是abstract(抽象)?

   当一个事物中的功能(函数)没有具体的实现时或对这个事物不能描述清楚时,这个事物称为抽象事物。

注意: 当一个类中有抽象方法的时候,这个类必须使用 抽象关键字修饰。

abstract(抽象)的用法如下所示:

//把狗和猫中的共性抽取到Animal类中
abstract class Animal
{
    abstract void eat();
}

抽象类:

使用某个类描述事物的时候,如果这个类中在描述这个事物的某个行为或功能的时候,只知道这个事物有这个行为或功能,但没有办法书写清楚具体的功能体,函数体,这时可以使用抽象函数来表示这个行为或功能,由于类中有抽象的函数,这个类就会变成抽象类。 

当一个类继承某个抽象类,这时这个类要把这个抽象类中的所有抽象方法全部复写。

//把狗和猫中的共性抽取到Animal类中
abstract class Animal
{
    abstract void eat();
}
​
class Dog extends Animal
{
    void eat()
    {
        System.out.println("啃骨头");
    }
    void lookHome()
    {
        System.out.println("看家");
    }
}
​
class Cat extends Animal
{
    
    //复写Animal类中的抽象函数eat
    void eat()
    {
        System.out.println("吃鱼");
    }
    void catchMouse()
    {
        System.out.println("抓老鼠");
    }
}
​
class AbstractDemo 
{
    public static void main(String[] args) 
    {
        Cat c = new Cat();
        c.eat();
    }
}

抽象类的特征

抽象类的特征总结起来可以说是 有得有失

有得:抽象类得到了拥有抽象方法的能力。

有失:抽象类失去了创建对象的能力。

其他成员(构造器,实例方法,静态方法等)抽象类都是具备的。

抽象类的注意事项

关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

  2. 抽象类中,可以有构造器,是供子类创建对象时,初始化父类成员使用的。

    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

  5. 抽象类存在的意义是为了被子类继承,抽象类体现的是模板思想。

    理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方法,交给具体的子类去实现。

抽象类存在的意义

抽象类存在的意义是为了被子类继承,否则抽象类将毫无意义,抽象类体现的是模板思想,模板是通用的东西抽象类中已经是具体的实现(抽象类中可以有成员变量和实现方法),而模板中不能决定的东西定义成抽象方法,让使用模板(继承抽象类的类)的类去重写抽象方法实现需求,这是典型的模板思想。