• 继承:基于已存在的类构造一个新类。
  • 超类(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" 规则:判断是否应该涉及为继承关系的简单规则。
  • 置换法则:程序中出现超类对象的任何地方都可以用子类对象置换。
  • 不能将一个超类的引用赋给子类变量。
  • 在覆盖一个方法的时候,子类方法的可见性不能低于超类方法的可见性

 

  • 理解方法调用:
  1. 编译器查看对象的声明类型方法名。如C类对象x,调用x.f(args),编译器会枚举所有C类中所有名为f的方法和其超类中所有public且名为f的方法。
  2. 匹配参数类型重载解析)。
  3. 如果是private方法static方法final方法或者构造器,则编译器可以确定调用的是哪个方法(静态绑定)。
  4. 程序运行,采用动态绑定时,虚拟机调用与x所引用的对象的实际类型最合适(可能存在类型转换)的那个类的方法。

 

  • 阻止继承 :final类(不允许扩展的类)和final方法(子类不允许覆盖的方法)。
  • 有时候也可能需要将某个类的对象引用转换成另一个对象引用。进行类型转换的唯一原因:在暂时忽视对象的实际类型之后,使用对象的全部功能
  • 良好的习惯:在进行类型转换之前,先检查是否能够成功转换(借助 instanceof操作符 ),否则可能抛出ClassCastException。
  • 总结:1.只能在继承层次内进行类型转换  2.转换之前,进行 instanceof 检查。3.一般,应尽量少类型转换和instanceof运算符。

 

  • 抽象类:
  1. 抽象类,只作为派生其他类的通用基类,而作为想使用的特定的实例类。abstract关键字。
  2. 包含一个或多个抽象方法的类必须被声明为抽象的(抽象类可以包含具体的数据和具体方法)。public abstract class Person{...}。
  3. 抽象方法:使用abstract关键字声明的方法,就不需要实现这个方法,(充当一个占位的作用)。如: public abstract String getDescription();
  4. 注意:抽象类虽不可被实例化,但是可以定义一个抽象类的对象变量(引用它的子类的对象,动态绑定)。
  • 示例程序(测试抽象类:创建一个“人”的抽象类,派生出“员工”类和“学生”类,并打印它们的信息)
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();
	}

}

 

  • 受保护访问:
  1. 关键字protected。超类的某些方法允许被子类访问,或者允许子类的方法访问超类的某个域。如:若将超类Employee的hireDay域设为protected,那么Manager类的方法只能够访问Manager对象的hireDay域,而不能访问Employee对象的hireDay域。
  2. protected声明的域 谨慎使用:多少违背了OOP的封装原则。具体地说:子类能够访问超类的这个域,就可能依赖于这个域,那么当超类中这个域需要改动时,需要告知所有使用了这个类的人。
  3. protected方法更具实际意义,能够限制方法的使用。比如:clone方法。
  • 可见性归纳:
  1. private : 只对本类可见。
  2. public : 对所有类可见。
  3. protected : 子类以及同包可见。
  4. 默认(无修饰符):同包可见。