zoukankan      html  css  js  c++  java
  • Java核心技术 继承

    超类和子类:

    父类也叫超类

    超类的private属性并不能被子类访问。假如我们编写一个Manager类继承Employee类。

    public class Manager extends Employee
    {
    private double bonus;
    . . .
    public void setBonus(double bonus)
    {
    this.bonus = bonus;
    }
    }

    Manager类的计算薪水方式肯定与Emplyee不同,因为它多了一个奖金bonus,那么我们应该怎么重写这个类呢?

    public double getSalary()
    {
    return salary + bonus; // won't work
    }

    或许会采用上面的方式,实际上,这样会报错,原因就是子类并不能直接访问父类的private属性,尽管Manager继承了这个属性。

    此时只能通过父类的getSalary方法来得到salary属性,可以使用关键字super:

    public double getSalary()
    {
    double baseSalary = super.getSalary();
    return baseSalary + bonus;
    }

    有些人认为,super与this引用是类似的概念,实际上super并不是一个对象的引用,不能将super赋给另一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字。

    并且,子类可以增加覆盖父类的域或方法,但不能删除继承的任何域和方法。

     

    子类可以隐式的调用父类默认的构造方法。 
    如果父类没有默认构造方法,必须显示调用。 

     

    多态、动态绑定:

    一个对象变量可以指示多种实际类型的现象被称为多态。

    假设我们有如下语句:

    Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);
    boss.setBonus(5000);
    Employee[] staff = new Employee[3];
    staff[0] = boss;
    staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
    staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);
    for (Employee e : staff)
    System.out.println(e.getName() + " " + e.getSalary());

    那么将会在控制台输出如下信息:

    Carl Cracker 85000.0
    Harry Hacker 50000.0
    Tommy Tester 40000.0

    这里很奇怪,为什么e能够判断出是Employee对象还是Manager对象呢,这里就是我们说的多态(一个对象变量可以指示多种实际类型)。

    那么什么是动态绑定呢?

    首先弄清对象方法的执行过程:

    1.编译器属性查看该类和其父类中方法名相同的方法(父类同时还需要该方法为public)。

    2.接下来,编译器查找参数类型相同的方法,并执行,如果在这个过程存在多个方法与之匹配,就会报告错误。

    上面的过程就称为动态绑定,虚拟机一定调用与对象方法的实际类型最适合的那个方法,也就是说,如果在子类中找到该方法,即执行子类的方法,否则就去父类中寻找。

    如果是privatestaticfinal方法,那么编译器可以准确知道掉哦那个哪个方法,这种调用方式称为静态绑定。

    由于每次调用方法都需进行搜索,开销很大,所以虚拟机预先为每一个类建立一个方法表,如图:

    在运行的时候,也就是调用e.getSalary时,解析过程如下:

    1.首先提取e的实际类型方法表,可能是Employee,也可能是Manager。

    2.在方法表中搜索签名相同的方法。

    3.虚拟机调用该方法。

     

    阻止继承

    有时候,不希望利用某个类定义子类。不允许扩展的类被称为final类。如果在定义类的时候利用了final修饰符就表明该类是final类。

    类中特定的方法也可以被声明为final,这样子类就不能覆盖这个方法,final类中的所有方法都自动称为final方法。

     

    受保护访问:

    当我们把某个方法或者域的可访问标识设置为proteced时,表明这个类是受保护的,也就是说同个包以及其子类都能够访问。

    但是这里有一个限定,假设我们把hireDay域设为proteced,那么Manager类只能访问Manager对象中的hireDay域而不能访问其他Employee对象的hireDay域。

    这里有点混乱,个人认为机制是这样的:

    子类继承父类,无论其属性的访问性为什么,都会被继承。也就是private的也会被继承到子类,但是子类不能访问继承来的private属性。

    当设置为proteced时,同样被继承,但是此时可以访问,访问的是其本身对象继承来的域。所以不能访问其他对象的域。

     

    equals方法:

    Object类中的equals方法用于检测一个对象是否等于另一个对象。在Object中,这个方法将判断两个对象是否具有相同的引用。然而,对大多数类来说,这种判断并没有什么意义。经常需要检测两个对象状态的相等性,如果俩个个对象的状态相等,就认为这两个对象相等。

    如比较两个雇员对象的姓名、薪水、和雇佣日期都一样,那就认为它们是相等的。

    public class Employee
    {
    . . .
    public boolean equals(Object otherObject)
    {
    // a quick test to see if the objects are identical
    if (this == otherObject) return true;
    // must return false if the explicit parameter is null
    if (otherObject == null) return false;
    // if the classes don't match, they can't be equal 返回对象所属的类
    if (getClass() != otherObject.getClass())
    return false;
    // now we know otherObject is a non-null Employee
    Employee other = (Employee) otherObject;
    // test whether the fields have identical values
    

    return Objects.equals(name, other.name)
    && salary == other.salary
    && Object.equals(hireDay, other.hireDay);

    
    }
    }

    在子类中定义equals方法时,首先调用父类的equals,如果检测失败,那就不相等,如果检测成功,则继续比较子类中的实例域:

    public class Manager extends Employee
    {
    . . .
    public boolean equals(Object otherObject)
    {
    Chapter 5 Inheritance 230
    if (!super.equals(otherObject)) return false;
    // super.equals checked that this and otherObject belong to the same class
    Manager other = (Manager) otherObject;
    return bonus == other.bonus;
    }
    }

    有的人不会采用getClass(),而是采用如下的语句:

    if (!(otherObject instanceof Employee)) return false;

    实际上,这样做有可能出错。

    如果x.equals(y)是相等的,那么y.equals(x)应该也是相等的,那么如果采用上面的语句,

    当我们调用e.queals(m),其中e是Employee的对象,m是Manger的对象,那么返回的结果是相等的,如果反过来调用呢:

    m.queals(e),这就使得Manager类受到了束缚,因为e并没有拥有m特有的那部分信息!

    接下来的判断就会出现错误!

    另外,每一个对象拥有一个属于增加的散列码,如果x.equslas(y)返回true,那么x.hashCode == y.hashCode也应该返回true.

  • 相关阅读:
    B1001 害死人不偿命的(3n+1)猜想 (15 分)
    A1050 String Subtraction (20 分)
    A1041 Be Unique (20 分)
    B1047 编程团体赛 (20 分)
    B1043 输出PATest (20 分)
    B1042 字符统计 (20 分)
    B1038 统计同成绩学生 (20 分)
    VB计算符号
    vs2008写代码的时候不能输入中文,sogou和google输入法都没有用
    如何彻底关闭Windows7自动更新
  • 原文地址:https://www.cnblogs.com/Darlietoothpaste/p/6700417.html
Copyright © 2011-2022 走看看