zoukankan      html  css  js  c++  java
  • 【JAVA基础】类---------多态

    多态存在的三个条件

    1、有继承关系  

    2、子类重写父类方法  

    3、父类引用指向子类对象

    补充一下第二点,既然多态存在必须要有“子类重写父类方法”这一条件,那么以下三种类型的方法是没有办法表现出多态特性的(因为不能被重写):

    1、static方法,因为被static修饰的方法是属于类的,而不是属于实例的

    2、final方法,因为被final修饰的方法无法被子类重写

    3、private方法和protected方法,前者是因为被private修饰的方法对子类不可见,后者是因为尽管被protected修饰的方法可以被子类见到,也可以被子类重写,但是它是无法被外部所引用的,一个不能被外部引用的方法,怎么能谈多态呢

    代码当中体现多态性,其实就是一句话:父类引用指向子类对象。

    格式:
    父类名称 对象名 = new 子类名称();
    或者:
    接口名称 对象名 = new 实现类名称();
    

    示例:

    public class Fu {
    
        public void method() {
            System.out.println("父类方法");
        }
    
        public void methodFu() {
            System.out.println("父类特有方法");
        }
    }
    ===================
    ublic class Zi extends Fu {
    
        @Override
        public void method() {
            System.out.println("子类方法");
        }
    }
    =====================
    public class Demo01Multi {
    
        public static void main(String[] args) {
            // 使用多态的写法
            // 左侧父类的引用,指向了右侧子类的对象
            Fu obj = new Zi();
    
            obj.method();
            obj.methodFu();
        }
    }

    多态中成员变量和成员方法的访问规则:

    成员变量:编译看左边,运行还看左边。
    成员方法:编译看左边,运行看右边。

    public class Fu  {
    
        int num = 10;
    
        public void showNum() {
            System.out.println(num);
        }
    
        public void method() {
            System.out.println("父类方法");
        }
    
        public void methodFu() {
            System.out.println("父类特有方法");
        }
    }
    ===============================
    public class Zi extends Fu {
    
        int num = 20;
        int age = 16;
        @Override
        public void showNum() {
            System.out.println(num);
        }
        @Override
        public void method() {
            System.out.println("子类方法");
        }
        public void methodZi() {
            System.out.println("子类特有方法");
        }
    }
    =============================
    public class Demo01MultiField {
        public static void main(String[] args) {
            // 使用多态的写法,父类引用指向子类对象
            Fu obj = new Zi();
            System.out.println(obj.num); // 父:10
           //System.out.println(obj.age); // 错误写法!成员变量运行和编译看左面
            System.out.println("=============");
    
            // 子类没有覆盖重写,就是父:10
            // 子类如果覆盖重写,就是子:20
            obj.showNum();
            System.out.println("=============");
            obj.method(); // 父子都有,优先用子
            obj.methodFu(); // 子类没有,父类有,向上找到父类
        }
    }
    

     

    向上转型和向下转型

    1、向上转型是自动的。即Father f = new Children()是自动的,不需要强转

    2、向下转型要强转。即Children c = new Father()是无法编译通过的,必须要Children c = (Children)new Father(),让父类知道它要转成具体哪个子类

    3、父类引用指向子类对象,子类重写了父类的方法,调用父类的方法,实际调用的是子类重写了的父类的该方法。即Father f = new Children(),f.toString()实际上调用的是Children中的toString()方法

    4、向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。解决方案:用对象的向下转型【还原】。

    instanceof方法

    如何才能知道一个父类引用的对象,本来是什么子类?

    格式:
    对象 instanceof 类名称
    

    使用接口或者父类作为方法参数,既可以多态写法,也可以用实现类对象。两者都会向上转型。

    public interface USB {
    
        public abstract void open(); // 打开设备
    
        public abstract void close(); // 关闭设备
    
    }
    ===========================
    // 鼠标就是一个USB设备
    public class Mouse implements USB {
        @Override
        public void open() {
            System.out.println("打开鼠标");
        }
    
        @Override
        public void close() {
            System.out.println("关闭鼠标");
        }
    
        public void click() {
            System.out.println("鼠标点击");
        }
    }
    ===========================
    // 键盘就是一个USB设备
    public class Keyboard implements USB {
        @Override
        public void open() {
            System.out.println("打开键盘");
        }
    
        @Override
        public void close() {
            System.out.println("关闭键盘");
        }
    
        public void type() {
            System.out.println("键盘输入");
        }
    }
    ============================
    public class Computer {
    
        public void powerOn() {
            System.out.println("笔记本电脑开机");
        }
    
        public void powerOff() {
            System.out.println("笔记本电脑关机");
        }
    
        // 使用USB设备的方法,使用接口作为方法的参数
        public void useDevice(USB usb) {
            usb.open(); // 打开设备
            if (usb instanceof Mouse) { // 一定要先判断
                Mouse mouse = (Mouse) usb; // 向下转型
                mouse.click();
            } else if (usb instanceof Keyboard) { // 先判断
                Keyboard keyboard = (Keyboard) usb; // 向下转型
                keyboard.type();
            }
            usb.close(); // 关闭设备
        }
    
    }
    ==============================
    public class DemoMain {
    
        public static void main(String[] args) {
            // 首先创建一个笔记本电脑
            Computer computer = new Computer();
            computer.powerOn();
    
    
            USB usbMouse = new Mouse(); // 首先进行向上转型,多态写法
            // 参数是USB类型,我正好传递进去的就是USB鼠标
            computer.useDevice(usbMouse);
    
            // 创建一个USB键盘
            Keyboard keyboard = new Keyboard(); // 没有使用多态写法
            // 方法参数是USB类型,传递进去的是实现类对象
            computer.useDevice(keyboard); // 正确写法!也发生了向上转型
            // 使用子类对象,匿名对象,也可以
    //        computer.useDevice(new Keyboard()); // 也是正确写法,也发生了向上转型
    
            computer.powerOff();
            System.out.println("==================");
    
        }
    
    }
    

      

  • 相关阅读:
    杨老师课堂_VBA学习教程之一键合并所有文件
    无题
    杨老师课堂_VBA学习教程之VBA中使用函数
    杨老师课堂_Java核心技术下之控制台模拟文件管理器案例
    杨老师课堂之JavaScript定时器_农夫山泉限时秒杀案例
    交换机级联,堆叠,集群技术介绍
    IP划分
    光纤
    交换机
    URL中“#” “?” &“”号的作用
  • 原文地址:https://www.cnblogs.com/paulwinflo/p/12978127.html
Copyright © 2011-2022 走看看