• 菜鸡的Java笔记 第二十三


    abstractClass 抽象类的概念
            1.抽象类的基本定义
            2.抽象类的使用原则
            
            不会抽象类与接口,java = 没学
            
            如果说现在在一个类之中需要定义一个没有方法体的方法,那么可以利用adstract关键字来进行抽象方法的定义
            而包含有抽象方法的类就可以使用abstract来定义成为抽象类
            类的核心组成:属性,方法。但是在学习完继承操作之后,会发现子类存在有一种覆写父类方法的机制,而且这一机制直接与对象的多态性有关
            于是这样就会出现一个问题:假设现在使用的是普通类,并且在这个类里面有一个println()方法

    class A{
        public void print(){
            System.ot.println("**************");
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            
        }
    }

           
            但是这个A类在设计之初有一个要求,希望继承它的子类一定要覆写这个 print()方法。但是事实上这个时候的子类完全可以灵活的选择是否需要覆写方法

    class A{
        public void print(){
            System.ot.println("**************");
        }
    }
    class B extends A{}
    public class abstractClass{
        public static void main(String args[]){
            
        }
    }

               
            但是由于只是一个普通方法,所以对于子类是否覆写没有任何的要求,于是这样就会出现一个漏洞,父类无法强制要求子类覆写方法
            如果只依靠普通类的继承,那么根本就不能够对子类产生限制,所以就可以利用抽象类和抽象方法来解决此类问题
            范例:定义抽象类

    abstract class A{
        public void fun(){
            System.ot.println("**************");
        }
        public abstract void print();//没有方法体,使用 abstract 声明
    }
    class B extends A{}
    public class abstractClass{
        public static void main(String args[]){
            
        }
    }

               
            抽象方法的特点: 一个是使用了 abstract 关键字定义,另外一个是方法的后面没有“{}”,表示没有方法体
            范例:错误的使用抽象类

    abstract class A{
        public void fun(){
            System.ot.println("**************");
        }
        public abstract void print();//没有方法体,使用 abstract 声明
    }
    // class B extends A{}
    public class abstractClass{
        public static void main(String args[]){
            A a = new A();
        }
    }            

            本处直接采用了关键字new实例化了抽象类对象,但是在程序编译的时候就会出现的错误信息“A是抽象的:无法实例化”
            抽象类是不能够直接进行对象实例化操作的,因为一旦类的对象实例化了,就意味着可以调用类中的所有方法了,但是抽象方法只是一个声明,并没有具体的方法体
            所以在实际的开发之中,抽象类的使用原则如下:
                抽象类必须有子类,子类利用 extends关键字来继承抽象类,一个子类只能够继承一个父类
                抽象类的子类(如果不是抽象类)那么必须要覆写抽象类中的全部抽象方法
                抽象类可以利用对象的向上转型机制,通过子类对象进行实例化操作
                
    不能直接产生实例化对象的分析:
            当一个类对象实例化之后就意味着,需要进行属性的堆内存分配,同时该对象可以调用类中的全部方法
            而抽象类中有抽象方法,抽象方法没有方法体,你如何调用呢?

    abstract class A{
        public void fun(){
            System.ot.println("**************");
        }
        public abstract void print();//没有方法体,使用 abstract 声明
    }
    class B extends A{
        public void print(){
            System.out.println("这个方法是强制子类要覆写的方法");
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            A a = new B(); // 向上转型
            a.print();  // 被子类所覆写过的方法
        }
    }
    /*
    结果:
    这个方法是强制子类要覆写的方法
    */

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

    */

    /*     抽象类的相关说明
            整个的设计结构里面多了抽象类的定义,那么多;了一个定义之后,就需要与原始的结构有一些对比
            0.抽象类允许提供构造方法,如果抽象类父类提供的是有参构造,则子类必须使用 super() 明确的去调用父类的指定构造方法
    1.抽象类不能使用final关键字来定义,因为抽象类必须有子类,而final不能有子类
            2.抽象类就是比普通类多了抽象方法而已,但是普通类中的所有结构抽象类都可以定义,包括普通方法,构造方法,属性,常量等内容:
                而且子类对象也符合于对象实例化流程,默认先调用父类中的无参构造,而后再执行子类自己的构造操作

    abstract class A{
        public static final String INFO = "HELLO";
        public A(){
            this.fun();
        }
        public void fun(){
            System.out.println("**************");
        }
        public abstract void print();//没有方法体,使用 abstract 声明
    }
    class B extends A{
        public void print(){
            System.out.println("这个方法是强制子类要覆写的方法");
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            A a = new B(); // 向上转型
            a.print();  // 被子类所覆写过的方法
        }
    }
    /*
    结果:
    *******************
    这个方法是强制子类要覆写的方法
    */

           
            思考题:

    abstract class A{
        
        public A(){
            this.fun();
        }
        public abstract void print();//没有方法体,使用 abstract 声明
    }
    class B extends A{
        private int num = 50;
        public B(int num){
            this.num = num;
        }
        public void print(){
            System.out.println("num ="+this.num);
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            new B(100);
            
        }
    }
    /*
    结果:
    num = 0
    */

               
            本程序的解决关键思路:子类对象实例化前一定要先实例化父类对象,也就是说此时,子类对象的属性都没有内容
                分析:

    abstract class A{
        public A(){  // 2.默认调用父类构造
            this.fun();// 3.调用println()方法
        }
        public abstract void print();//没有方法体,使用 abstract 声明
    }
    class B extends A{
        private int num = 50;
        public B(int num){ // 1.传递内容过来,在子类对象实例化前先实例化父类对象
            this.num = num;
        }
        public void print(){ // 4.调用此方法执行,此时子类对象还未实例化,内容没有赋值
            System.out.println("num ="+this.num);// 5.只能够输出对应数据的类型默认值
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            new B(100);
            
        }
    }

               
            3. 抽象类中可以没有抽象方法,但是依然不可能使用关键字new进行对象的实例化操作

    abstract class A{
        
    }
    public class abstractClass{
        public static void main(String args[]){
            A a = new A();
            
        }
    }
    //结果:出错

               
                因为类A上存在有 abstract 关键字,所以此处无法进行对象的直接实例化
            
            4.外部抽象类上不允许使用static声明,但是内部抽象中可以使用 static声明,这样表示的是一个外部抽象类
            范例:定义普通的内部抽象类

    abstract class A{
        public abstract void printA();
        abstract class B{
            public
             abstract void printB();
        }
    }
    class X extends A{
        public void printA(){}
        class Y extends B{
            public void printB(){
                
            }
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            A a = new A();
            
        }
    }
    //结果:

           
            范例:在内部抽象类中使用 staic 关键字

    abstract class A{
        public abstract void printA();
         static abstract class B{
            public abstract void printB();
        }
    }
    class X extends A.B{
        public abstract void printB(){}
    }
    public class abstractClass{
        public static void main(String args[]){
            A a = new A();
            
        }
    }

               
            5.抽象类中可以存在有 static方法,而且 static 方法不受实例化对象的控制
            范例:直接通过抽象类产生实例化对象

    abstract class A{// 设计之初考虑到N年后的发展,需要有子类,但是N年前不需要子类
        public abstract void printA();
        private static class B extends A { // 在A类里面直接定义实现的子类
            public void printA(){
                System.out.println("**************");
            }
        }
        public static A getlnnstance(){  // 取得
            return new B();
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            A a = A.getlnnstance();
            a.printA();
        }
    }

               
            日后如果发现在系统类库中有某个抽象类可以直接利用一个 static 方法取得实例化对象的时候不要觉得陌生

    abstract class A{            
        public abstract void printA();
        private static class B extends A { // 在A类里面直接定义实现的子类
            public void printA(){
                System.out.println("**************");
            }
        }
        public static A getlnnstance(){  // 取得
            return new B();
        }
    }
    class C extends A{ // N年以后
        public void printA(){
            System.out.println("***************");
        }
    }
    public class abstractClass{
        public static void main(String args[]){
            A a = A.getlnnstance();
            a.printA();
            A a1 = new C();  // 留给用户做的
            a1.printA();
        }
    }

               
            以上出现的几种形式有些是在后面讲解系统类库中会出现的问题,现阶段看看就完了

    */

    /*    抽象类实际应用--模版设计模式
            清楚了抽象类产生动机以及使用之后,下面就必须搞清楚一个问题,抽象类与普通类到底有那些区别?
            现在假设有三个物种;
                机器人:补充能量+工作
                人:吃饭+工作+睡觉
                猪:吃+睡
            现在要求实现一种命令的模式,不管是何物种,只要传递指定的指令就可以进行操作
            范例:实现程序操作

    abstract class Action{// 定义的是行为,行为一定不是具体的
        public static final int EAT = 1;
        public static final int SLEEP = 2;
        public static final int WPRK = 5;
        public void command(int flag){// 执行命令
            switch(flag){// 数值用 switch 判断最好
                case EAT:{
                    this.eat();
                    break;
                }
                case SLEEP:{
                    this.sleep();
                    break;
                }
                case WORK:{
                    this.work();
                    break;
                }
            }
        }
        public abstract void eat();// 因为这些具体的行为如何执行不知道   交由子类根据自己的实际情况完成
        public abstract void sleep();
        public abstract void work();
    }
    class Robot extends Action{
        public void eat(){
            System.out.println("机器人补充能量");
        }
        public void sleep(){}
        public void work(){
            System.out.println("机器人正在工作");
        }
    }
    class Person extends Action{
        public void eat(){
            System.out.println("人在吃饭");
        }
        public void sleep(){
            System.out.println("人在休息");
        }
        public void work(){
            System.out.println("人在工作");
        }
    }
    class Pig extends Action{
        public void eat(){
            System.out.println("猪在吃");
        }
        public void sleep(){
            System.out.println("猪在睡");
        }
        public void work(){}
    }
    // 不同的子类有着自己不同的操作支持
    public class abstractClass{
        public static void main(String args[]){
            
        }
    }

               
            范例:程序测试

    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){// 数值用 switch 判断最好
                case EAT:{
                    this.eat();
                    break;
                }
                case SLEEP:{
                    this.sleep();
                    break;
                }
                case WORK:{
                    this.work();
                    break;
                }
            }
        }
        public abstract void eat();// 因为这些具体的行为如何执行不知道   交由子类根据自己的实际情况完成
        public abstract void sleep();
        public abstract void work();
    }
    class Robot extends Action{
        public void eat(){
            System.out.println("机器人补充能量");
        }
        public void sleep(){}
        public void work(){
            System.out.println("机器人正在工作");
        }
    }
    class Person extends Action{
        public void eat(){
            System.out.println("人在吃饭");
        }
        public void sleep(){
            System.out.println("人在休息");
        }
        public void work(){
            System.out.println("人在工作");
        }
    }
    class Pig extends Action{
        public void eat(){
            System.out.println("猪在吃");
        }
        public void sleep(){
            System.out.println("猪在睡");
        }
        public void work(){}
    }
    // 不同的子类有着自己不同的操作支持
    public class abstractClass{
        public static void main(String args[]){
            fun(new Pig());
            System.out.println("*********************");
            fun(new Robot());
            System.out.println("*********************");
            fun(new Person());
        }
        public static void fun(Action act){  // 接收的是行为
            act.eat();
            act.sleep();
            act.work();
        }
    }

               
    这样的设计就是将抽象类设计为了一个模版,如果要想实现这个模版的功能,子类就必须按照要求进行指定方法的覆写
            而关于这一设计的应用,在以后学习到的 Servlet 程序设计上就要采用到        

    现在在整个程序之中,如果某一类事物需要实现特定的功能,那么就必须按照Action所定义的方法进行覆写
            这个时候类必须按照父类提供的模版编写代码

            总结
                1.抽象类的设计是在普通类之上的抽象类
                2.抽象类关键的问题就是约定了子类必须要覆写的抽象方法
                3.抽象类的使用原则:
                    抽象类必须有子类,子类利用 extends关键字来继承抽象类,一个子类只能够继承一个父类
                    抽象类的子类(如果不是抽象类)那么必须要覆写抽象类中的全部抽象方法
                    抽象类可以利用对象的向上转型机制,通过子类对象进行实例化操作


    */

  • 相关阅读:
    下载MySQL数据库
    2012开源项目计划-WPF企业级应用整合平台
    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法
    WPF入门教程系列(一) 创建你的第一个WPF项目
    一、什么是WPF?
    asp.net页面间传值的几种方法
    .NET 代码编译过程
    全面认识.NET框架(一)
    C#里partial关键字的作用(转摘)
    .NET概念:.NET程序编译和运行
  • 原文地址:https://www.cnblogs.com/mysterious-killer/p/10105335.html
Copyright © 2020-2023  润新知