使用abstract修饰的抽象类

目录

为什么需要有抽象类

抽象类的作用

抽象类的使用规则

抽象类的使用注意点

栗子1:利用对象多态性向上转型创建抽象类实例

栗子2:使用一个内部类继承抽象类


为什么需要有抽象类

当子类继承父类时,对于父类的方法,子类可以自由选择是否重写该方法,此时重写并不是强制发生的,父类不能强制地要求子类重写一个方法。

若是父类强制子类必须将方法重写,那么此时便可以将父类定义为抽象类。

抽象类的出现,允许父类强制子类重写自己的某个方法,此时子类别无选择只能重写该方法。

抽象类的作用

经过上面的描述,抽象类的作用便很清楚了:抽象类强制子类重写父类的方法。

抽象类的使用规则

  1. 抽象类使用abstract关键字定义
    abstract class 类名 {
    
    }
    

  2. 抽象类不能直接使用new关键字
    abstract class demo_1 {
    
    }
    
    public class demo_2 {
        public static void main(String[] args) {
            demo_1 d = new demo_1();
        }
    }
    

    这段代码是错误的,编译器会抛出错误提示,因为demo_1是一个抽象类,不允许直接使用new关键字创建对象

  3. 抽象类必须提供子类,子类使用extends继承一个抽象类
  4. 抽象类的子类必须重写抽象类的方法
    abstract class class1 {
        abstract void method1();
    }
    
    public class class2  extends class1{
        @Override
        void method1() {
            System.out.println("method1");
        }
    }

    在上面的代码中,子类class2必须重写(或者说是实现可能更为恰当一些)class1的抽象方法

  5. 抽象类的对象实例化可以利用对象多态性向上转型来完成创建

抽象类的使用注意点

  1. 在定义抽象类时,不能使用final关键字进行修饰,因为抽象类是必须有一个子类的,而用final关键字修饰的类,没有子类
  2. 抽象类与普通类并没有很大的差别,只是抽象类在普通类的基础上提供了抽象方法
  3. 抽象类中允许不存在任何抽象方法(但是抽象类中没有抽象方法。。。。。那还是不要定义为抽象类比较好吧)
  4. 即使抽象类中不存在任何抽象方法,但是抽象类仍旧是抽象类,仍旧无法使用new关键字直接创建一个抽象类的对象(这边有情多态欺骗大师上场解决这个问题q(≧▽≦q))
  5. 可以在抽象类中使用static关键字进行修饰,静态方法是不受到抽象类的限制的

栗子1:利用对象多态性向上转型创建抽象类实例

抽象类不可以直接使用new关键字创建一个抽象类实例,但是可以利用多态性来向上转型创建抽象类
虽然规定是这么规定,但是也只是编译器认为创建了一个抽象类实例,但实际在运行时,执行的还是子类的方法

分析下面的代码段便可以验证

abstract class class1 {
    abstract void method1();

    void show() {
        System.out.println("这是父类的show方法");
    }
}

public class class2 extends class1 {
    @Override
    void method1() {
        System.out.println("method1");
    }

    void show() {
        System.out.println("这是子类的show方法");
    }
}

public class class3 {
    public static void main(String[] args) {
        class1 c = new class2();
        c.method1();
        c.show();
    }
}

 class1是一个抽象类,类中有一个必须子类重写的method1()方法和一个子类可以选择重写也可以选择不重写的show()方法。

class2是抽象类class1的子类,在class2中实现了抽象方法method1(),重写了父类的show()方法。

class3中有一个main()方法以几句验证代码。

分析class3,首先利用对象的多态性,创建了一个变量c,c在编译时被认为是class1类,即抽象类/父类实例,在运行时被认为是class2类,即子类实例。总之在这方面,多态确实能称得上是一个欺骗大师(就逮着编译器欺骗了🤣🤣🤣)。

接着,调用了变量c的method()方法以及show()方法。

仔细想想,从这一步也是可以看出来一些端倪的,c是可以调用method1()方法的,但是在父类中,该方法是一个抽象方法,只有方法的声明,并没有方法的定义,只有在子类中才有具体的method1()方法定义,那么在这里便可以大胆的猜测,实际上c是class2类的对象。

当然,也可以调用c.getClass();来看一看c究竟是哪一个类的对象。(输出的结果是class2,上面的猜测是正确的)

运行程序后,得到的结果是这样的:

 那么此时也成功验证了,利用对象多态性向上转型创建抽象类确实是可行的。

栗子2:使用一个内部类继承抽象类

①抽象类是无法直接使用new关键字直接创建一个抽象类对象

②抽象类的子类使用extends关键字继承抽象类

此时来折磨一下自己,若是:

  1. 非要使用new关键字
  2. 不想使用extends关键字

在这样的要求下,是否还可以好好地玩抽象类

答案是可以的,请看下面的代码段:

abstract class demo_1 {
    abstract void show();

    void show1() {
        System.out.println("这是抽象类的show1");
    }
    
    void show2() {
    }
}


public class demo_2 {
    public static void main(String[] args) {
        //这是一个匿名的demo_2的内部类
        demo_1 d = new demo_1() {
            void show() {
                System.out.println("这是d对象的show");
            }
            void show2() {
                System.out.println("这是d对象的show2");
            }
        };
        d.show();
        d.show1();
        d.show2();
        System.out.println(d.getClass());
        
        //这是另一个匿名的demo_2的内部类
        demo_1 d1 = new demo_1() {
            void show() {
                System.out.println("这是d1对象的show");
            }
        };
        d1.show();
        d1.show1();
        System.out.println(d1.getClass());
    }
}

接下来分析这一段代码:

有一个抽象类demo_1,类里面有一个亟待实现的抽象方法show(),还有一个普通方法show1()

有一个类demo_2,里面有一个main()方法,main方法中有一段代码

在上面的代码段中,有两段内容形式上有一些奇怪

 //这是一个匿名的demo_2的内部类
        demo_1 d = new demo_1() {
            void show() {
                System.out.println("这是d对象的show");
            }
            void show2() {
                System.out.println("这是d对象的show2");
            }
        };


//这是另一个匿名的demo_2的内部类
        demo_1 d1 = new demo_1() {
            void show() {
                System.out.println("这是d1对象的show");
            }
        };

但这两段代码的定义是正确的,它表明在demo_2类中构造了两个内部类,这两个内部类没有显式地给出类名,这是两个匿名内部类,并且这两个匿名内部类继承自demo_1类,即抽象类。

第一个匿名内部类中实现抽象方法show()以及重写了show2()方法

第二个匿名内部类中实现了抽象方法show()

但是需要注意的是,这两个匿名内部类继承自抽象类,因此,实现的方法必须是抽象类中所有的抽象方法,重写的方法必须是抽象类中已经存在的普通方法(实际上也可以在这两个匿名内部类中新增抽象类中没有的普通方法,编译器并不会报错,但是新增的普通方法是无法调用的)。因此若是加上下面这段内容,编译器便会报错。

demo_1 d = new demo_1() {
            void show() {
                System.out.println("这是d对象的show");
            }

            void show2() {
                System.out.println("这是d对象的show2");
            }
            void show3() {
                System.out.println("这是d对象的show3");
            }
        };
d.show3(); //这一句会报错,编译不通过

 至于为什么会报错,这边可以吐槽一句多态不愧是专业欺骗编译器。

运行程序,可以得到下面的结果:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值