前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java——抽象类(基本概念、使用原则、模板设计模式)

Java——抽象类(基本概念、使用原则、模板设计模式)

作者头像
Winter_world
发布2020-09-25 10:30:32
1.5K0
发布2020-09-25 10:30:32
举报

抽象类相当之重要,不会抽象类与接口,相当于没学过Java。

1、抽象类的基本概念

若在一个类中要定义一个没有方法体的方法,可以利用abstract关键字进行抽象方法定义,而包含抽象方法的类就可以使用abstract来定义为抽象类。

为什么会出现抽象类的概念?有什么作用?

类的核心组成包括属性和方法,但是学习完继承后,可知子类存在一种覆写父类方法的机制,这一机制与对象的多态性相关。但是这样会出现一个问题,假设现在使用的是普通类,类中有个print()方法。但类设计之初有个要求,希望继承它的方法一定要覆写print()方法,但是这个只是一个普通方法,子类是否覆写没有任何要求,这时候会出现一个漏洞,即父类无法强制要求子类必须覆写方法。所以需要抽象类和抽象方法来解决此类问题。

【举例】:定义抽象类

代码语言:javascript
复制
abstract class A{
    public void fun(){
        System.out.println("hello");
    }
    public abstract void print();//没有方法体,使用abstract声明
}

抽象方法 的特点:一个是使用abstract关键字定义,一个是方法后面没有{},即没有方法体。

【举例】:错误的使用抽象类

以上可知,抽象类不能直接进行实例化操作,因为一旦类的对象实例化了,意味着可以调用类中的方法,但是抽象类是没有方法体的。所以,在实际开发中,抽象类的使用原则:

  • 抽象类必须有子类,子类利用extends关键字来继承抽象类,一个子类只能继承一个父类;
  • 抽象类的子类(如果不是抽象类),必须覆写抽象类中的全部抽象方法;
  • 抽象类可以利用对象的向上转型机制,通过子类进行实例化操作;
代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            A a = new B();
            a.print();
    }
}
abstract class A{
    public void fun(){
        System.out.println("hello");
    }
    public abstract void print();//没有方法体,使用abstract声明
}
class B extends A{
    @Override
    public void print() {
        System.out.println("子类必须覆写的方法");
    }
}

抽象类与普通类相比,最大的好处就是强制定义了子类的实现要求,本质上讲,抽象类就是比普通类多了一些抽象方法的定义而已。实际开发设计中,父类的设计最重要,普通类相比于抽象类,抽象类的约束更加严格,所以实际开发中,几乎不会出现普通类定义子类的情况,大多数都是继承抽象类。

2、抽象类的相关说明

学到这里,整个设计结构中多了抽象类的定义,需要与原始的结构进行下对比:

1)抽象类不能使用final关键字定义,因为抽象类必须要有子类,而final不能有子类;

2)抽象类就是比普通类多了抽象方法,必须用abstract关键字声明,但是普通类中的所有结构抽象类都可以定义,包括:属性、普通方法、构造方法、常量等,且子类对象也符合对象实例化流程,默认先调用父类中的无参构造方法,再执行子类自己的构造。

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            A a = new B();
            a.print();
    }
}
abstract class A{
    public static final String INFO = "HELLO";
    public A(){
        this.fun();
    }
    public void fun(){
        System.out.println("hello");
    }
    public abstract void print();//没有方法体,使用abstract声明
}
class B extends A{
    @Override
    public void print() {
        System.out.println("子类必须覆写的方法");
    }
}

【举例】:观察如下一个有意思的大坑思考题(了解即可)

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            A a = new B(10);
    }
}
abstract class A{
    public A(){  //2.默认调用父类构造
        this.print();//3.调用该方法
    }
    public abstract void print();//没有方法体,使用abstract声明
}
class B extends A{
    private int num=1;

    public B(int num) { //1.传递内容,子类对象实例化前先要实例化父类对象
        this.num = num;
    }
    @Override
    public void print() { //4.调用此方法执行,但是此时子类对象还未实例化,内容默认值为0
        System.out.println(this.num); //5.只能够输出对应数据类型的默认值
    }
}

3)抽象类中可以没有抽象方法,但是仍不能使用关键字new直接进行抽象类的实例化操作;

4)外部抽象类不允许使用static声明,但是内部抽象类中可以,这样表明的是一个外部抽象类;

【举例】:定义普通的内部抽象类

代码语言:javascript
复制
abstract class A{
    public abstract void printA();
    abstract class B{
        public abstract void printB();
    }
}

class X extends A{
    @Override
    public void printA() {}
    class Y extends B{
        @Override
        public void printB() {

        }
    }
}

【举例】:在内部抽象类中使用static

代码语言:javascript
复制
abstract class A{
    public abstract void printA();
    static abstract class B{
        public abstract void printB();
    }
}

class X extends A.B{
    @Override
    public void printB() {
        
    }
}

5)抽象类中可以存在static方法,static方法不受实例化控制

【举例】:直接通过抽象类产生实例化对象

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        A a = A.getInstance();
        a.printA();
    }
}
abstract class A{//考虑日后应用需要有子类
    public abstract void printA();
    private static class B extends A{ //在A类中直接定义实现的子类
        @Override
        public void printA() {
            System.out.println("Hello");
        }
    }
    public static A getInstance(){
        return new B();
    }
}

若发现系统类库中抽象类有直接用static方法取得实例化对象,可能就是用的以上方式。

以上出现的几种形式,有的是后面讲解系统类库中会出现的问题,目前了解即可。

3、模板设计模式

抽象类与普通类具体有什么区别?打个比方,有三个物种:

  • 机器:补充能量+工作;
  • 人:吃饭+工作+睡觉;
  • 猪:吃饭+睡觉;

现在要求实现一种命令模式,不管何种物种,只有传递指定的指令就可以进行操作。

【举例】:实现程序操作

1)行为的父类:

代码语言:javascript
复制
abstract class Action{//定义行为,不是具体的
    public static final int EAT =1;
    public static final int SLEEP =2;
    public static final int WORK =5;

    public void command(int flag){//执行命令
        switch (flag){
            case EAT:
                this.eat();
                break;

            case SLEEP:
                this.sleep();
                break;

            case WORK:
                this.work();
                break;

                default:
                    break;
        }
    }
    public abstract void eat(); //交由子类,根据实际情况完成
    public abstract void sleep();
    public abstract void work();
}

2)定义子类:

代码语言:javascript
复制
class Robot extends Action{
    @Override
    public void eat() {
        System.out.println("机器人补充能量");
    }
    @Override
    public void sleep() {}
    @Override
    public void work() {
        System.out.println("机器人正在工作");
    }
}

class Person extends Action{
    @Override
    public void eat() {
        System.out.println("人在吃饭");
    }
    @Override
    public void sleep() {
        System.out.println("人在休息");
    }
    @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() {}
}

3)程序测试:

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        fun(new Robot());
        System.out.println("********************");
        fun(new Person());
        System.out.println("********************");
        fun(new Pig());
        System.out.println("********************");
    }

    public static void fun(Action act){
        act.eat();
        act.sleep();
        act.work();
    }
}

现在的程序中,某一类事物需要实现特定的功能,那么就必须按照Action定义的方法进行覆写,子类必须按照父类提供的模板进行代码设计,所以这种设计叫做模板设计。

4、总结

1)抽象类的设计是在普通类之上的抽象,普通类描述的是具体事物,抽象类描述了多个类之间的共同点;

2)抽象类关键的问题是约定了子类必须覆写的抽象方法;

3)抽象类的使用原则:

  • 抽象类必须有子类,子类利用extends关键字来继承抽象类,一个子类只能继承一个父类;
  • 抽象类的子类(如果不是抽象类),必须覆写抽象类中的全部抽象方法;
  • 抽象类可以利用对象的向上转型机制,通过子类进行实例化操作;
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-04-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、抽象类的基本概念
  • 2、抽象类的相关说明
  • 3、模板设计模式
  • 4、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档