Java abstract抽象

1 抽象类

1.1 什么是抽象类

        使用抽象关键字abstract声明的类是抽象类,抽象类不能直接实例化创建对象。

        这个定义看上去非常茫然,究其原因是因为在面向对象设计时候,会利用“泛化”将子类的共同属性和方法抽取出来设计出父类,此时的父类往往是半成品类,只包含部分属性和方法,甚至属性值都没有合理初始化,如下图所示:

        如果直接创建对象并且使用有可能造成各种不理想结果,甚至是异常故障。

        可以用抽象父类来解决这个问题。

1.2 抽象类示例

        为便于理解抽象类的作用,我们先开发一个不使用抽象类的案例,查看此时可能存在的问题。

/**
 * Person类的作用是为子类提供代码复用
 */
public class Person {
    String name;
    int age;

    public void whoru() {
        System.out.println("我是"+name);
    }
}

package day07.abstract01;
public class Student extends Person{
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void study() {
        System.out.println("学习");
    }
}

package day07.abstract01;
public class Teacher extends Person{
    public Teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void teach() {
        System.out.println("讲课");
    }
}

package day07.abstract01;
public class Worker extends Person{
    public Worker(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void work() {
        System.out.println("工作");
    }
}

package day07.abstract01;

public class AbstractDemo1 {
    public static void main(String[] args) {
        Student s = new Student("Tom", 12);
        Teacher t = new Teacher("Andy", 28);
        Worker w = new Worker("Jerry", 28);

        s.whoru();
        s.study();

        t.whoru();
        t.teach();

        w.whoru();
        w.work();

        //问题:如果能够直接创建Person对象,其方法运算结果不理想
        Person p = new Person();
        p.whoru();
    }
}

        上面案例的运行结果如下所示:

        上述运行结果中创建Person类型对象,调用其whoru()方法,得到结果是null。

        这个结果并不理想,就像生活中问一个人是谁,回答“佚名”一样。造成这个结果的原因是:泛化出来的父类Person 是个半成品类,创建其对象后,其name属性没有合理初始化,导致输出了name的默认值 null。

        如何解决上述问题呢?需要明确表示 Person是一个半成品类,不能直接实例化。

        因此,就可以使用abstract修饰一下Person类型,使其成为抽象类,这样Java的编译器就会限制Person类型,不允许其直接实例化创建对象。不能被实例化,就不可能造成后续结果了。所以合理使用abstract类,可以避免创建不应该创建的对象,减少程序的错误。

        将上述案例中的Person类声明为抽象类,可避免出现创建半成品实例的情况。案例代码示意如下:

/**
 * Person类的作用是为子类提供代码复用
 */
public abstract class Person {
    String name;
    int age;

    public void whoru() {
        System.out.println("我是"+name);
    }
}

package day07.abstract02;
public class AbstractDemo2 {
    public static void main(String[] args) {
        Student s = new Student("Tom", 12);
        Teacher t = new Teacher("Andy", 28);
        Worker w = new Worker("Jerry", 28);

        s.whoru();
        s.study();

        t.whoru();
        t.teach();

        w.whoru();
        w.work();

        //问题:如果能够直接创建Person对象,其方法运算结果不理想
        //Java编译器检查,不允许创建抽象类型的对象!
        //Person p = new Person();
        //p.whoru();
    }
}

1.3 抽象类不可以实例化

        面向对象设计时候根据子类泛化得到的半成品父类,应该定义为抽象类,这样可以限制创建半成品类的对象,减少意外的错误发生。

        正因为抽象类不可以被实例化,因此 abstract 和 final 不可以同时修饰一个类:final 关键字使得类不可被继承,而抽象类既不能能被继承,又不能被实例化,则没有任何意义。

        使用抽象类时:

        1、在类名前面添加abstract关键字以后就是抽象类了

        2、抽象类可以作为父类被子类继承,可以定义变量

        3、抽象类不能直接创建对象

2 抽象方法

2.1 什么是抽象方法

        使用abstract关键字声明,不包含方法体的方法称为抽象方法。

        这个定义同样晦涩,究其原因是因为在利用泛化设计父类时候,有这种情况全体子类都有相同的方法,但是每个具体方法实现都并不相同,这样只能将方法名抽取到父类,方法体留在每个子类中,这种只有方法名称的方法,就是抽象方法。

2.2 抽象方法的语法

        抽象方法的语法:

        1、使用abstract声明方法,不能有方法体

        2、包含抽象方法的类必须声明为抽象类,因为包含抽象方法的类一定是不完整的半成品类

        3、子类继承抽象类时候必须重写(实现)抽象方法,否则出现编译错误

  • 可以将抽象方法看作父类对子类的行为约定,必须被子类重写实现

        实际使用时,如何选择抽象方法?建议规则:每个子类都有,但是每个子类实现都不同的方法泛化为抽象方法!

        定义抽象类,并包含抽象方法;定义子类继承自抽象类,并重写抽象方法。编写代码测试其特点。

        案例示意代码如下:

/**
 * Person类的作用是为子类提供代码复用
 * 设计为抽象类,只能被继承,不能创建对象
 */
public abstract class Person {
    String name;
    int age;

    public void whoru() {
        System.out.println("我是"+name);
    }

    /**
     * 日程计划
     */
    public abstract void schedule();
}

package day07.abstract03;
public class Student extends Person {
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void study() {
        System.out.println("学习");
    }

    public void schedule() {
        System.out.println("吃饭、听课");
    }
}

package day07.abstract03;
public class Student extends Person {
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void study() {
        System.out.println("学习");
    }

    public void schedule() {
        System.out.println("吃饭、听课");
    }
}

package day07.abstract03;
public class Worker extends Person {
    public Worker(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void work() {
        System.out.println("工作");
    }

    public void schedule() {
        System.out.println("吃饭、开车");
    }
}

package day07.abstract03;
public class AbstractDemo3 {
    public static void main(String[] args) {
        Student s = new Student("Tom", 12);
        Teacher t = new Teacher("Andy", 28);
        Worker w = new Worker("Jerry", 28);

        s.schedule();
        t.schedule();
        w.schedule();
    }
}

        综合抽象类和抽象方法的讲解,可以简单理解抽象类的意义如下:

  • 为其子类提供一个公共的类型
  • 封装子类中的重复内容(成员变量和方法)
  • 定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的
  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangyan_1010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值