Java第十课_抽象和多态

4.面向对象的编程_抽象和多态

  • 抽象

    public class Practice {
        public static void main(String[] args) {
            Student.say();
        }
    }
    
    public abstract class Student {
        /*
            abstract : 表示抽象的 , 可以用来修饰类和函数
                抽象的本质, 是从一类事物中抽取特征, 归纳总结出统一的属性和方法.
                抽象可能不实现具体功能, 更像是一种模板.
                    因此不可以创建对象或调用具体功能, 主要用来被子类继承, 然后子类再将方法实现, 完成具体的功能
    
            abstract修饰的类称为 抽象类
                格式 :   修饰符  abstract  class  类名{}
            abstract修饰的函数称为 抽象函数
                格式 :   修饰符  abstract  返回值类型   函数名(形式参数) ;
    
            注意 :
                1.抽象函数必须位于抽象类,但抽象类中不一定有抽象函数
                2.即便抽象类中没有抽象函数,它依然不能创建对象
                    抽象类是有构造器的,用于子类创建对象时调用
                3.子类继承抽象父类时,自然会继承父类中的抽象函数,
                    因此子类要么也声明为抽象类(GaoEr), 要么重写抽象函数(GaoYi),实现具体功能
    
            模板法 : 当程序的一部分是确定的,另一部分是不确定,
                确定部分在抽象父类写好, 不确定部分只做抽象声明, 具体功能交由子类来完成
            模板法是多线程的原理.
    
            abstract 关键字不能与哪些关键字一起使用?
            1.private
            2.static
            3.final
    
            static 不能跟 this super 一起使用
        */
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public abstract void study() ;
    
        public static void say(){// static的属性或函数依然可以用类名直接调用
            System.out.println("aaa");
        }
    }
    
    public class GaoYi extends Student{
        // 同一个体系,才可以继承
        public GaoYi() {
        }
    
        public GaoYi(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void study() {
            System.out.println("高一学生学习高一内容.....");
        }
    }
    
    public abstract class GaoEr extends Student{
    
    }
    
  • 接口

    public class Practice {
    
        public static void main(String[] args) {
            /*
                interface 接口, 和class不同
                    接口是一种规范, 和继承类似, 也是抽象的. 没有具体功能, 需要靠class来实现接口
                类与类之间 : 单继承,支持多层继承
                接口与类之间 : 多实现(类可以implements多个接口), 也支持多层实现
                    类来实现接口,类实现接口后,具备继承特征 : 类是子类 , 接口是父类
                接口与接口之间 : 多继承关系,支持多层继承
    
                同一个体系继承. 不同体系之间,有类似的行为, 使用接口
                    继承: 动物->鸟类->鹰
                    接口: 鹰<-飞行->飞机
             */
    
            IA.m4();
            IAImpl ia = new IAImpl();
            ia.m3();
        }
    }
    
    public interface IA {
        /*
            接口是没有构造器的.
    
            JDK8.0/1.8 之前接口只有两个成员
            1.常量 :      public static final 数据类型  常量名 = 初始值 ;
            2.抽象函数 :   public abstract  返回值类型  函数名(形式参数) ;
    
            注意: 这两种成员修饰符是固定的, 接口中的缺省即是默认这两种, 不再是default
    
            JDK8.0/1.8 之后接口多了default声明(默认级别函数), 是非抽象函数
                之前都是abstract函数, 接口一旦有方法变动, 其子类(实现类)均需要实现.
                现在可以用default, 有变动时, 子类可以根据需求,选择是直接继承还是重写.
         */
        public static final double PI = 3.14;
        public abstract boolean m1();
        int m2(int num);// public abstract
    
        default void  m3(){// 非抽象函数, 不再强迫子类(实现类)实现.
            System.out.println("default IA 函数 m3");
        }
    
        static void m4(){// 接口的静态成员依然可以用接口名直接访问
            System.out.println("静态函数 m4");
        }
    }
    
    public class IAImpl extends Object implements IA{// 先声明继承,再声明接口. 可以声明多个接口
        // m1,m2函数必须重写实现, m3不需要
        //@Override
        public boolean m1() {
            return false;
        }
    
        //@Override
        public int m2(int num) {
            return 0;
        }
    }
    
  • 多态

    public class Practice {
    
        public static void main(String[] args) {
            /*
                多态 : 同一个事物的多种形态
                前提 : 1.类继承  2.函数重写 3.向上转型
             */
            Animal animal = new Animal();
            animal.eat();
            Cat cat2 = new Cat();
            cat2.eat();
    
            // 向上转型 : 父类变量 来接收 子类对象的引用.     基本数据类型的自动类型转换
            // 向上转型后会失去子类特有功能. 通过父类变量可以访问, 访问的实际结果也是子类, 但不可以直接访问子类特有函数
            Animal animal2 = new Cat();
            animal2.eat();
            // animal2.catchMouse();// error
    
            // 向下转型 : 将父类变量转换为子类类型          基本数据类型的强制类型转换
            Cat cat3 = (Cat) animal2;
            cat3.catchMouse();
    
            // instanceof : 判断前面的对象是否是后面这个类的类型
            //     可以通过这个语句来判断, 有问题直接处理, 避免运行异常
            // 格式 :  对象名  instanceof  类型
            System.out.println(animal instanceof Cat);
            System.out.println(animal2 instanceof Cat);
    
            System.out.println("---------------------------------------------");
            Cat cat = new Cat();
            function(cat);
    
            // 多态只和函数有关, 和成员变量无关, 即便父类变量实际指向子类, 访问成员变量时依然是父类的成员变量
            //     看起来地址实际指向子类, 应该访问子类的成员变量. 但这涉及java隐藏域的内容, 不必深究. 当做特性,记住结论即可
            System.out.println("---------------------------------------------");
            System.out.println(animal2.num);// 110
            System.out.println(cat2.num);// 120
        }
    
        public static void function(Animal animal){// Animal animal = cat ;
            if (animal instanceof Animal) {
                animal.eat();
            }
            if (animal instanceof Cat) {
                ((Cat) animal).catchMouse();
            }
        }
    }
    
    public class Animal {
    
        int num = 110;
    
        public void eat() {
            System.out.println("动物吃...");
        }
    
        public void sleep() {
            System.out.println("动物睡觉");
        }
    }
    
    public class Cat extends Animal {
    
        int num = 120;
    
        @Override
        public void eat() {
            System.out.println("猫吃鱼.....");
        }
    
        public void catchMouse() {
            System.out.println("猫抓老鼠!!!!");
        }
    }
    
posted @ 2023-12-22 23:18  张心野  阅读(22)  评论(0)    收藏  举报