继承
继承概念
从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并扩展新的能力。继承避免了对一般类和特殊类之间共同特征进行的重复描述。
关键字extends表示继承,如 A extends B 则表示A继承B,A获取B的属性和行为。
A称为 子类(subclass) 、 派生类(derived class)或 孩子类(child class)。
B称为 超类(superclass)、父类(parent class)或 基类(base class)。
简单的判断:如果是”is-a”关系,用继承。例如 老师 是 人,人 是 动物。
例:现在需要构造学生Student类和Teacher类。
因为所有的人都有姓名,性别,年龄,先构造一个person类作为两者的父类。
class Person
{
private String name; // 姓名
private String sex; // 性别
private int age; // 年龄
public Person(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public void who ()
{
System.out.println("a person");
}
}
所有的老师和学生都是人,都会用到上面的属性,所以老师类和学生类可以直接继承Person类省去姓名性别等属性和基本的方法的编写。
学生又有学号。老师又有职位,所带课的班级。所以在其各自类里加上其特有的属性。
class Teacher extends Person{ // 老师
private String Class; // 带课班级
private String Position; // 职位
public Teacher(String name, String sex, int age, String Class, String position) {
super(name, sex, age);
this.Class = Class;
this.position = position;
}
public void who ()
{
System.out.println("a teacher");
}
}
class Student extends Person{ // 学生
private int id; // 学号
public Student(String name, String sex, int age, int id)
{d
super(name, sex, age);
this.id = id;
}
public void who ()
{
System.out.println("a Student");
}
}
访问控制
访问权限修饰符
修饰符 | 同一个类 | 同一个包 | 子类 | 所有类 |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
因为封装的缘故,最好将属性定义为private。但这样一来子类就无法访问所继承的父类的属性。
所以应在加入相应的get,set方法,或者将父类的属性定义为protect。
继承层次
由父类派生出来的所有类的集合被称为继承层次。
Java不支持多继承,一个类只能有一个父类,但能有多个子类。
例:老师类和学生类继承Person类,中学生和大学生继承学生类。则他们的继承层次如下图
方法的重写(override)
超类中的某些方法对于子类并不适用,所以需要对方法进行重写。
例如 Person中的who()方法打印 “a person”,但如果你想要跟具体一点,那就要重写Teacher类中的who()方法。如让其打印 ”a teacher“。同理 重写Student类中的方法让其打印 “a student”
// Teacher类
public void who ()
{
System.out.println("a teacher");
}
// Student类
public void who ()
{
System.out.println("a Student");
}
注:重写一个方法使,子类方法不能低于父类方法的可见性。如果父类方法是public,子类的方法一定要声明为public。不然编译器将会把它解释成更严格的访问权限,从而无法调用。
this 和 super
this的两种用途:
- 引用隐式参数
- 调用该类的其他构造器
super的两种用途:
- 调用超类的方法
- 调用超类的构造器
例:Teacher类中的构造器
public Teacher(String name, String sex, int age, String Class, String position) {
super(name, sex, age);
this.Class = Class;
this.position = position;
}
this隐式调用参数:
方法中的参数变量可以和其外部的其他变量重名。
比如Teacher类中有 Class班级属性,方法中也可以定义名为Class的变量,这时方法里的Class默认表示新定义的,如果需要调用类中的Class,就需要这样调用this.Class。
super调用超类的构造器:
调用
super(name, sex, age);
就等同于调用了
public Person(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
阻止继承-final类和方法
如果希望阻止人们继承某个类,则可以在类前加final修饰词修饰,则表示该类不可被继承。
如希望Teacher类不可被继承,则可以这样写。
final class Teacher extends Person {......}
如果某人想要写一个类继承Teacher则会发生错误。
class EnglishTeacher extends Teacher {......}
// 错误 Cannot inherit from final 'Teacher'
如果希望阻止人们重写所继承的类的某个方法,则可以在方法加final修饰词修饰,则表示该方法不可被重写。
如不希望Person类的子类重写其who()方法,则可以这样写
public final void who ()
{
System.out.println("a person");
}
现在Student类重写who()方法就会发生错误。
public void who () { ......}
// 错误 overridden method is final