- 继承:基于已存在的类构造一个新类。
- 超类(superclass)、子类(subclass)。
- 关键字extends表示继承。
- 子类可以增加 域、方法 或者 覆盖 方法,但绝不能删除继承的任何域和方法。
- 注意:子类不能访问超类的私有域,需要借助 super关键字。
- 子类构造器必须调用超类构造器对超类的私有域进行初始化,需借助super关键字。如果子类构造器没有显式地调用超类的构造器,则将自动调用超类默认的构造器。
- 一个对象变量可以指示多种实际类型的现象称为多态。在运行时能够自动选择调用哪个方法的现象称为动态绑定(dynamic binding)。
- 在Java中,不需将方法声明为虚拟方法。若不希望某方法有虚拟特征,用final标记。
- 示例程序:(用一个员工数组引用经理对象和员工对象,并将他们的信息分别打印出来)
package coreJava_4_1;
public class Test4_1 {
public static void main( String args[]) {
Employee[] staff = new Employee[3];
Manager boss = new Manager("Riddle", 8000, 2020, 7, 24 );
boss.setBonus(5000);
staff[0] = boss;
//注意:不能够调用 staff[0].setBonus(5000);因为在编译器的角度,staff[0]是一个Employee对象
staff[1] = new Employee("Harry", 5000, 2005, 7, 20 );
staff[2] = new Employee("Ryon", 3000, 2005, 3, 14 );
for( Employee e : staff ) {
System.out.println( "name: " + e.getName() + ", salary: " + e.getSalary() + ", hireday: " + e.getHireDay().toString() );
}
}
}
package coreJava_4_1;
import java.time.*;
public class Employee {
private String name;
private double salary;
private LocalDate hireDay;
public Employee( String name, double salary, int year, int month, int day ) {
this.name = name;
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public LocalDate getHireDay() {
return hireDay;
}
}
package coreJava_4_1;
public class Manager extends Employee {
private double bonus;
public Manager( String name, double salary, int year, int month, int day) {
super(name, salary, year, month, day);
bonus = 0;
}
public void setBonus( double bonus ) {
this.bonus = bonus;
}
public double getSalary() {
double baseSalary = super.getSalary();
return baseSalary + bonus;
}
}
- "is-a" 规则:判断是否应该涉及为继承关系的简单规则。
- 置换法则:程序中出现超类对象的任何地方都可以用子类对象置换。
- 不能将一个超类的引用赋给子类变量。
- 在覆盖一个方法的时候,子类方法的可见性不能低于超类方法的可见性。
- 理解方法调用:
- 编译器查看对象的声明类型和方法名。如C类对象x,调用x.f(args),编译器会枚举所有C类中所有名为f的方法和其超类中所有public且名为f的方法。
- 匹配参数类型(重载解析)。
- 如果是private方法、static方法和final方法或者构造器,则编译器可以确定调用的是哪个方法(静态绑定)。
- 程序运行,采用动态绑定时,虚拟机调用与x所引用的对象的实际类型的最合适(可能存在类型转换)的那个类的方法。
- 阻止继承 :final类(不允许扩展的类)和final方法(子类不允许覆盖的方法)。
- 有时候也可能需要将某个类的对象引用转换成另一个对象引用。进行类型转换的唯一原因:在暂时忽视对象的实际类型之后,使用对象的全部功能 。
- 良好的习惯:在进行类型转换之前,先检查是否能够成功转换(借助 instanceof操作符 ),否则可能抛出ClassCastException。
- 总结:1.只能在继承层次内进行类型转换 2.转换之前,进行 instanceof 检查。3.一般,应尽量少类型转换和instanceof运算符。
- 抽象类:
- 抽象类,只作为派生其他类的通用基类,而不作为想使用的特定的实例类。abstract关键字。
- 包含一个或多个抽象方法的类必须被声明为抽象的(抽象类可以包含具体的数据和具体方法)。public abstract class Person{...}。
- 抽象方法:使用abstract关键字声明的方法,就不需要实现这个方法,(充当一个占位的作用)。如: public abstract String getDescription();
- 注意:抽象类虽不可被实例化,但是可以定义一个抽象类的对象变量(引用它的子类的对象,动态绑定)。
- 示例程序(测试抽象类:创建一个“人”的抽象类,派生出“员工”类和“学生”类,并打印它们的信息)
package coreJava_4_5;
public class Test4_5 {
public static void main( String args[] ) {
Person[] people = new Person[2];
people[0] = new Student( "James", "Biology" );
people[1] = new Employee( "Kevin", 8000, 2012, 8, 15 );
for( Person p : people )
System.out.println( p.getDescription() );
}
}
package coreJava_4_5;
public abstract class Person {
private String name;
public Person( String name ) {
this.name = name;
}
public String getName() {
return name;
}
public abstract String getDescription();
}
package coreJava_4_5;
public class Student extends Person {
private String major;
public Student( String name, String major ) {
super(name);
this.major = major;
}
@Override
public String getDescription() {
return "a student named " + super.getName() + ", major in " + major;
}
}
package coreJava_4_5;
import java.time.*;
public class Employee extends Person {
private double salary;
private LocalDate hireDay;
public Employee(String name, double salary, int year, int month, int day ) {
super(name);
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
}
@Override
public String getDescription() {
return "an employee named " + super.getName() + " with a salary of " + salary + " hired on " + hireDay.toString();
}
}
- 受保护访问:
- 关键字protected。超类的某些方法允许被子类访问,或者允许子类的方法访问超类的某个域。如:若将超类Employee的hireDay域设为protected,那么Manager类的方法只能够访问Manager对象的hireDay域,而不能访问Employee对象的hireDay域。
- protected声明的域 谨慎使用:多少违背了OOP的封装原则。具体地说:子类能够访问超类的这个域,就可能依赖于这个域,那么当超类中这个域需要改动时,需要告知所有使用了这个类的人。
- protected方法更具实际意义,能够限制方法的使用。比如:clone方法。
- 可见性归纳:
- private : 只对本类可见。
- public : 对所有类可见。
- protected : 子类以及同包可见。
- 默认(无修饰符):同包可见。