概念:
- 继承是Java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
- 继承实现软件复用的重要手段。
- 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承的优点:
- 提高代码的重用性.
- 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性。
- 提高代码的可扩展性,提高产品或项目的开放性。
继承的特性:
- Java 语言的继承是单继承,不允许一个类继承多个父类。
- 子类不能继承父类的构造器。
- 子类是父类的一个超集。它可能比父类含有更多的方法,但它必须至少具备父类中所有的方法。
- 继承可以把子类向上转换成父类,这是向上转型的一种表现。
- 继承最重要的方面是用来表现父类和子类之间的关系。这种关系可以用“子类是父类的一种类型”。
继承的语法:
已存在的类被称为超类(super class)、基类(base class)或父类(parent class)。
新类被称为子类(subclass)、派生类(derived class)或孩子类(child class)。
父类
public class Father {
//父类中的成员属性
public String name;
public int age;
public char sex;
// 父类中的成员方法
public void say(){
System.out.println("我会说话");
}
public void eat(){
System.out.println("我会吃饭");
}
}
子类
public class Son extends Father {
public String grade;
// 子类中的成员方法
public void sleep(){
System.out.println("我会睡觉");
}
public void study(){
System.out.println("我会学习");
}
}
尽管在 Son 类中没有显式地定义 name / age / sex等属性, say() 和 eat() 等方法,但属于 Son 类的对象也可以使用它们,因为Son类自动地继承了超类 Father 中的这些方法。
Java类虽然只能有一个直接父类, 但它可以有无限多个间接父类。例:
class Father extends Grandfather{...}
class Son extends Father{...}
重写父类的方法
子类继承了父类,所以说子类是一个特殊的父类.。大部分时候, 子类总是以父类为基础。额外增加新的成员变量和方法。但有一种情况例外:子类需要重写父类的方法。
例如鸟类都包含了飞翔的方法,但其中的鸵鸟并不会飞, 因为鸵鸟是鸟的子类, 因此它将从鸟类中获得飞翔的方法, 但这个飞翔的方法显然不适合鸵鸟, 所以鸵鸟这个子类需要重写鸟类(父类)的方法。
下面先定义一个 Bird 类
public class Bird
{
//Bird 类的 fly() 方法
public void fly()
{
System.out.println("Birds are flying!");
}
}
下面定义一个 Ostrich 类, 这个类继承了 Bird 类,同时重写 Bird 类的 fly() 方法。
public class Ostrich
{
//重写 Bird 类的 fly() 方法
public void fly()
{
System.out.println("I can't fly!");
}
public static void main(String[] args)
{
//创建 Ostrich 对象
Ostrich os = new Ostrich();
//执行 Ostrich 对象的 fly() 方法, 将会输出 "I can't fly!"
os.fly();
}
}
运行上面的程序, 将看到执行 os.fly() 时执行的不是 Bird 类的 fly() 方法。
而是执行 Ostrich 类的 fly() 方法。
- 这种子类包含与父类同名方法的现象称为方法重写(Override),也被称为方法覆盖。可以说子类重写了父类的方法,也可以说子类覆盖了父类的方法。
方法的重写要遵循两同两小一大规则。
两同: 方法名相同 / 形参列表相同 。
两小: 子类方法返回值类型应比父类方法返回值类型小或相等。
子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等。
一大: 子类方法的访问权限应比父类方法的访问权限大或相等。
Super 关键字
前边有说到:子类不能继承父类的构造器。super关键字能解决这一问题。
super 关键字有两个用途:
一是调用超类的方法,二是调用超类的构造器。
super 不是一个对象的引用,不能将 super 赋给另一个对象变量,它只是一个指示编译器调用超类方法的特有关键字。
由于 Son 类的构造器不能访问 Father 类的私有域,所以必须利用 Son 类的构造器对这部分私有域进行初始化,我们可以通过 super 实现对超类构造器的调用。使用 super 调用构造器的语句必须是子类构造器的第一条语句。
继承的初始化过程
在继承关系中,子类具有父类相同的行为,当子类调用父类方法时,如何确保父类的实例域是正确初始化的?当初始化子类过程中,如何确保父类也得到正确的初始化?
public class Animal {
private static int A = printInit("static Animal region init");
public Animal()
{
System.out.println("--Animal--");
}
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{
private static int P = Animal.printInit("static Parrot region init");
public Parrot()
{
System.out.println("--Parrot--");
}
public static void main(String[] arg)
{
Parrot parrot = new Parrot();
}
}
运行结果:
static Animal region init
static Bird region init
static Parrot region init
--Animal--
--Bird--
--Parrot--