美文网首页
Java-基础-多态

Java-基础-多态

作者: 月沉眠love | 来源:发表于2019-08-15 16:05 被阅读0次

    在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写(Override)
    Person类

    class Person {
        public void run() {
            System.out.println("Person.run");
        }
    }
    

    Student类

    class Student extends Person {
        @Override
        public void run() {
            System.out.println("Student.run");
        }
    }
    

    Override和Overload不同的是,如果方法签名如果不同,就是Overload,Overload方法是一个新方法;如果方法签名相同,并且返回值也相同,就是Override。

    注意:

    方法名相同,方法参数相同,但方法返回值不同,也是不同的方法。#在Java程序中,出现这种情况,编译器会报错。

    加上@Override可以让编译器帮助检查是否进行了正确的覆写。希望进行覆写,但是不小心写错了方法签名,编译器会报错。
    但是@Override不是必需的

    多态

    Java的实例方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。

    这个非常重要的特性在面向对象编程中称之为多态

    public class Main {
        public static void main(String[] args) {
            // 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
            Income[] incomes = new Income[] {
                new Income(3000),
                new Salary(7500),
                new StateCouncilSpecialAllowance(15000)
            };
            System.out.println(totalTax(incomes));
        }
    
        public static double totalTax(Income... incomes) {
            double total = 0;
            for (Income income: incomes) {
                total = total + income.getTax();
            }
            return total;
        }
    }
    
    class Income {
        protected double income;
    
        public Income(double income) {
            this.income = income;
        }
    
        public double getTax() {
            return income * 0.1; // 税率10%
        }
    }
    
    class Salary extends Income {
        public Salary(double income) {
            super(income);
        }
    
        @Override
        public double getTax() {
            if (income <= 5000) {
                return 0;
            }
            return (income - 5000) * 0.2;
        }
    }
    
    class StateCouncilSpecialAllowance extends Income {
        public StateCouncilSpecialAllowance(double income) {
            super(income);
        }
    
        @Override
        public double getTax() {
            return 0;
        }
    }
    

    结果:800

    覆写Object方法

    因为所有的class最终都继承自Object,而Object定义了几个重要的方法:

    1.toString():把instance输出为String;
    2.equals():判断两个instance是否逻辑相等;
    3.hashCode():计算一个instance的哈希值。

    在必要的情况下,我们可以覆写Object的这几个方法。例如

    class Person {
        ...
        // 显示更有意义的字符串:
        @Override
        public String toString() {
            return "Person:name=" + name;
        }
    
        // 比较是否相等:
        @Override
        public boolean equals(Object o) {
            // 当且仅当o为Person类型:
            if (o instanceof Person) {
                Person p = (Person) o;
                // 并且name字段相同时,返回true:
                return this.name.equals(p.name);
            }
            return false;
        }
    
        // 计算hash:
        @Override
        public int hashCode() {
            return this.name.hashCode();
        }
    }
    

    调用super

    在子类的覆写方法中,如果要调用父类的被覆写的方法,可以通过super来调用。

    class Person {
        protected String name;
        public String hello() {
            return "Hello, " + name;
        }
    }
    
    Student extends Person {
        @Override
        public String hello() {
            // 调用父类的hello()方法:
            return super.hello() + "!";
        }
    }
    

    final

    继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final。用final修饰的方法不能被Override:

    class Person {
        protected String name;
        public final String hello() {
            return "Hello, " + name;
        }
    }
    
    Student extends Person {
        // compile error: 不允许覆写
        @Override
        public String hello() {
        }
    }
    
    如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记#为final。用final修饰的类不能被继承
    final class Person {
        protected String name;
    }
    
    // compile error: 不允许继承自Person
    Student extends Person {
    }
    

    对于一个类的实例字段,同样可以用final修饰。用final修饰的字段在初始化后不能被修改

    class Person {
        public final String name = "Unamed";
    }
    

    对final字段重新赋值会报错

    Person p = new Person();
    p.name = "New Name"; //compile error!
    

    可以在构造方法中初始化final字段:

    class Person {
        public final String name;
        public Person(String name) {
            this.name = name;
        }
    }
    

    总结:

    1、子类可以覆写父类的方法(Override),覆写在子类中改变了父类方法的行为;

    2、Java的方法调用总是作用于运行期对象的实际类型,这种行为称为多态;

    3、final修饰符有多种作用:

    4、final修饰的方法可以阻止被覆写;

    4、final修饰的class可以阻止被继承;

    4、final修饰的field必须在创建对象时初始化,随后不可修改。

    相关文章

      网友评论

          本文标题:Java-基础-多态

          本文链接:https://www.haomeiwen.com/subject/fjenjctx.html