一. 什么是继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
二. 继承的语法
关键字 extends 表明正在构造的新类派生于一个已存在的类。
public class Employee {
private String name;
private double salary;
private Date hireDay;
public Employee(String n, double s, int year, int month, int day)
{
name = n;
salary = s;
GregorianCalendar calendar = new GregorianCalendar(year, month, day);
hireDay = calendar.getTime();
}
public String getName() {
return name;
}
//more method
......
}
尽管 Employee 类是一个超类,但并不是因为它位于子类之上或者拥有比子类更多的功能。恰恰相反,子类比超类拥有的功能更加丰富。在 Manager 类中,增加了一个用于存储奖金信息的域,以及一个用于设置这个域的方法:
public class Manager extends Employee{//extends继承Employee类
...
private double bonus;
public void setBonus(double bonus) {
this.bonus = bonus;
}
}
然而,尽管在 Manager 类中没有显式地定义 getName 和 getHireDay 等方法,但属于 Manager 类的对象却可以使用它们,这是因为 Manager 类自动地继承了超类 Employee 中的这些方法。同样,从超类中还继承了 name、salary 和 hireDay 这 3 个域。这样一来,每个 Manager 类对象就包含了4个域:name、salary、hireDay 和 bonus。
在通过扩展超类定义子类的时候,仅需要指出子类与超类的不同之处。因此在设计类的时候,应该将通用的方法放到超类中,而将具
有特色用途的方法放在子类中,这种将通用的功能放到超类的做法,在面向对象程序设计中十分普遍。
然而,超类中的有些方法对子类 Manager 并不一定适用。例如,在 Manager 类中的 getSalary 方法应该返回薪水和奖金的总和。为此,需要提供一个新的方法来覆盖(override)超类中的这个方法:
@Override
public double getSalary() {
return salary + bonus;//won't work
}
然而,这个方法并不能运行。这是因为 Manager 类的 getSalary 方法不能直接地访问超类的私有域。也就是说,尽管每个 Manager 对象都拥有一个名为 salary 的域,但在 Manager 类的 getSalary 方法中并不能够直接地访问 salary 域。只有 Employee 类的方法才能够访问私有部分。如果 Manager 类的方法一定要访问私有域,就必须借助共有的接口,Employee 类中的共有方法正式这样一个接口。
@Override
public double getSalary() {
return super.getSalary() + bonus;
}
super 关键字有两个用途:一是调用超类的方法,二是调用超类的构造器。
super 不是一个对象的引用,不能将 super 赋给另一个对象变量,它只是一个指示编译器调用超类方法的特有关键字。
由于 Manager 类的构造器不能访问 Employee 类的私有域,所以必须利用 Employee 类的构造器对这部分私有域进行初始化,我们可以通过 super 实现对超类构造器的调用。使用 super 调用构造器的语句必须是子类构造器的第一条语句。
三. 继承初始化过程
public class Animal {
public Animal() {
System.out.println("--Animals--");
}
public static int printInit(String s) {
System.out.println(s);
return 30;
}
}
public class Bird extends Animal {
private static int B = Animal.printInit("static Bird region init");
public Bird(){
System.out.println("--Bird--");
}
}
public class Parrot extends Bird {
public Parrot(){
super();
System.out.println("--Parrot--");
}
public static void main(String[] arg) {
Parrot parrot = new Parrot();
}
}
运行结果:
--Animals--
--Bird--
--Parrot--
四. 继承的分类
纯继承关系是纯粹的“is-a”(是一种)关系,因为一个类的接口已经确定了它应该是什么。继承可以确保所有的导出类具有基类的接口,且绝对不会少。基类可以接收发送给导出类的任何消息,因为二者有着完全相同的接口。
五. 继承的特性
* Java 语言的继承是单继承,不允许一个类继承多个父类。
* java支持多层继承(继承体系)。
* 子类和父类是一种相对概念。
* 备注:顶层父类是Object类,所有的类默认都继承Object类。
1、继承后的特点---成员变量:
1. 子类只能获取父类非私有成员
2. 子父类的成员变量的名字不一样时,直接获取父类的成员变量
3. 子父类中成员变量名字是一样的
* 就近原则,谁离我近我就用谁
* 如果有局部变量就使用局部变量
* 如果没有局部变量,有子类的成员变量就使用子类的成员变量
* 如果没有局部变量和子类的成员变量,有父类的成员变量就使用父类的成员变量
* 备注:父类中的成员变量是非私有的,子类才可以直接访问。若父类中的成员变量私有了,子类不能直接访问的。
通常编码时,我们一般遵循封装的原则,可以在父类中提供公共的setXxx()和getXxx()方法。
例如:
public class ExtendsDemo2 {
public static void main(String[] args) {
Kid k = new Kid();
k.show();
}
}
class Dad{
String name="大葱";
}
class Kid extends Dad{
String name="二葱";
public void show() {
String name = "三葱";
System.out.println(super.name);
System.out.println(this.name);
System.out.println(name);
}
}
2:继承后的特点---成员方法:
1. 子父类的成员方法的名字不一样时,直接获取父类的成员方法
2. 子父类中成员方法名字是一样的
* 成员方法重名---重写(Override)
* 方法重写:子类出现于父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效应
也称为重写或者复写。声明不变,重新实现。
*重写的应用
子类可以根据需要,定义特定于自己的行为,即沿袭了父类的功能名称,又能根据子类的需要重新实现父类
的方法,从而进行扩展增强。
* 方法额重载:在一个类中,有多个重名的方法,但是其参数不一样
(参数的个数,参数的类型,参数的顺序),和返回值无关
备注:
1.子类方法重写覆盖父类方法时,必须保证权限大于等于父类的权限。
2.子类方法重写父类方法时,返回值类型,方法名和参数列表必须一模一样。
在没有使用@Override时,子类定义父类方法时,方法名和参数列表可变,返回值类型不可变。
六:继承的优点
在面向对象语言中,继承是必不可少的、非常优秀的语言机制,它有如下优点:
- 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
- 提高代码的重用性;
- 子类可以形似父类,但又异于父类;
- 提高代码的可扩展性,实现父类的方法就可以“为所欲为”了。
- 提高产品或项目的开放性。