zoukankan      html  css  js  c++  java
  • Java多态


    多态是同一个行为具有多个不同表现形式或者形态的能力。

    多态就是一个接口,使用不同的实例而执行不同操作,如图所示:

     多态存在的三个必要条件

    • 继承
    • 重写
    • 父类引用指向子类对象

    比如:

    Parent p=new Child();  

    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

    多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

    package pkg2020华南虎;
    
    /**
     *
     * @author yl
     */
    public class TestDuoTai {
    
        public static void main(String[] args) {
            show(new Cat());//Cat对象调用show方法
            show(new Dog00());//Dog对象调用show方法
            Animal00 a = new Cat();//向上转型
            a.eat();//调用Cat的eat方法
            Cat c = (Cat) a;//向下转型
            c.work();
        }
    
        public static void show(Animal00 a) {
            a.eat();
            if (a instanceof Cat) {
                Cat c = (Cat) a;
                c.work();
            } else if (a instanceof Dog00) {
                Dog00 c = (Dog00) a;
                c.work();
            }
        }
    }
    
    abstract class Animal00 {
    
        abstract void eat();
    }
    
    class Cat extends Animal00 {
    
        public void eat() {
            System.out.println("吃鱼");
        }
    
        public void work() {
            System.out.println("抓老鼠");
        }
    }
    
    class Dog00 extends Animal00 {
    
        public void eat() {
            System.out.println("吃骨头");
        }
    
        public void work() {
            System.out.println("看家");
        }
    }  

    虚函数

    虚函数的存在是为了多态。

    Java中其实没有虚函数的概念,他的普通函数就相当于C++的虚函数,动态绑定是Java的默认行为。如果Java中不希望某个函数具有虚函数特性,可以加上final关键字变成非虚函数。

    重写

    我们将介绍在Java中,当设计类时,被重写的方法的行为怎样影响多态性。

    我们已经讨论了方法的重写,也就是子类能够重写父类的方法。

    当子类对象调用重写方法时,调用的是子类的方法,而不是父类中被重写的方法。

    要想调用父类中被重写的方法,则必须使用关键字super

    package pkg2020华南虎;
    
    /**
     *
     * @author yl
     */
    public class EmployeeTest {
    
        private String name;
        private String address;
        private int number;
    
        public EmployeeTest(String name, String address, int number) {
            System.out.println("Employee构造函数");
            this.name = name;
            this.address = address;
            this.number = number;
        }
    
        public void mailCheck() {
            System.out.println("邮寄支票给:" + this.name + " " + this.address);
        }
    
        @Override
        public String toString() {
            return "EmployeeTest{" + "name=" + name + ", address=" + address + ", number=" + number + '}';
        }
    
        public String getName() {
            return name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public int getNumber() {
            return number;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
    package pkg2020华南虎;
    
    /**
     *
     * @author yl
     */
    
    
    public class Salary extends EmployeeTest {
    
        private double salary;//全年工资
    
        public Salary(String name, String address, int number, double salary) {
            super(name,address,number);
            setSalary(salary);
        }
        public void mailCheck(){
            System.out.println("Salary类的mailCheck方法");
            System.out.println("邮寄支票给:"+getName()+",工资为:"+salary);
        }
    
        public double getSalary() {
            return salary;
        }
    
        public void setSalary(double newsalary) {
            if(newsalary>=0.0)
            this.salary = newsalary;
        }
        public double computePay(){
            System.out.println("JI算工资,付给:"+getName());
            return salary/52;
        }
    }
    
    package pkg2020华南虎;
    
    /**
     *
     * @author yl
     */
    public class VirtualDemo {
        public static void main(String[] args) {
            Salary s=new Salary("员工A","北京",3,8888);
            EmployeeTest e=new Salary("员工B","上海",2,6666);
            System.out.println("使用Salary的引用调用mailCheck---");
            s.mailCheck();
            System.out.println("
    使用EmployeeTest的引用调用mailCheck---");
            e.mailCheck();
        }
    }  

    例子解析

    • 实例中,实例化了两个Salary对象:一个使用Salary引用s,另一个使用EmployeeTest引用e。
    • 当调用s.mailCheck()时,编译器在编译时会在Salary类中找到mailCheck(),执行过程JVM就调用Salary类的买了Check()。
    • 因为e是EmployeeTest的引用,所以调用e的mailCheck()方法时,编译器会去EmployeeTest类查找mailCheck()方法。
    • 在编译的时候,编译器使用EmployeeTest类中的mailCheck()方法验证该语句,但是在运行的时候,JVM调用的是Salary类中的mailCheck()方法。

    以上整个过程被称为虚拟方法调用,该方法被称为虚拟方法。

    Java中所有的方法都能以这种方式表现,因此,重写的方法能在运行时调用,不管编译的时候源代码中引用变量是什么数据类型。


    多态的实现方式

    • 方式一:重写Override
    • 方式二:接口
    • 方式三:抽象类和抽象方法

    什么他妈的叫他妈的惊喜!
  • 相关阅读:
    606. Construct String from Binary Tree
    696. Count Binary Substrings
    POJ 3255 Roadblocks (次短路)
    POJ 2823 Sliding Window (单调队列)
    POJ 1704 Georgia and Bob (博弈)
    UVa 1663 Purifying Machine (二分匹配)
    UVa 10801 Lift Hopping (Dijkstra)
    POJ 3281 Dining (网络流之最大流)
    UVa 11100 The Trip, 2007 (题意+贪心)
    UVaLive 4254 Processor (二分+优先队列)
  • 原文地址:https://www.cnblogs.com/2020yl/p/12272561.html
Copyright © 2011-2022 走看看