继承是一种类之间的关系,他描述了类之间一种“is a”的关系,继承也是面向对象编程的三大特性之一。
为什么要有继承,他有什么好处?提高代码的复用性,在不改变现有类的基础上不仅能够使用现有类的属性和功能,还能对现有类进行扩展。从上往下看,子类继承父类是子类对父类功能,属性的一种扩展,从下往上看,父类是对子类的进一步抽象,抽象出各个类之间的共同的属性和行为。
java继承
java中用extends关键字来实现一个类继承一个类。
举个栗子,有个学生类(Student)和老师类(Teacher):
/**
* @author helloliu
*/
//老师类
public class Teacher {
private String name;
private String sex;private String subject;
public void eat() {
System.out.println("人是铁,饭是钢,一顿不吃饿的慌。。。。。");
}
public void sleep() {
System.out.println("睡觉。。。。。");
}
public void teach () {
System.out.println(subject + "老师上课。。。。。");
}
}
//学生类
public class Student {
private String name;
private String sex;private int score;
public void eat() {
System.out.println("人是铁,饭是钢,一顿不吃饿的慌。。。。。");
}
public void sleep() {
System.out.println("睡觉。。。。。");
}
public void test() {
System.out.println("考试成绩 :" + score);
}
}
通过写这两个类我们可以发现,Student和Teacher他们有个共同的特性,他们都是人,name,sex,age,address,eat(),sleep()是他们的公有的属性和行为,那么我们就可以再进一步抽象出一个Person类,然后通过继承的方式写student和teacher类。
/**
* @author helloliu
*/
//Person类
public class Person {
private String name;
private String sex;public void eat() {
System.out.println("人是铁,饭是钢,一顿不吃饿的慌。。。。。");
}
public void sleep() {
System.out.println("睡觉。。。。。");
}
}
//Student类
public class Student extends Person{
private int score;
public void test() {
System.out.println("考试成绩 :" + score);
}
}
//Teacher类
public class Teacher extends Person{
private String subject;
public void teach () {
System.out.println(subject + "老师上课。。。。。");
}
}
对比之前的写法,使用继承的方式定义Student和Teacher类,看起来简洁很多,我们只是在类中写了他们独特的属性和方法。
继承的属性和行为
子类能够从父类继承父类的实例域和方法,但是对于私有方法,静态方法,final方法在子类中是不可见的,私有实例域可通过在父类中提供public方法来间接访问。
方法覆盖
父类中的某些方法,对于子类可能并不适用,他们的实现方式可能不同,我们可以在子类中对父类中已有的public和protected方法进行覆盖重写(override)。比如我们重写Student类的sleep方法。
/**
* @author helloliu
*/
public class Student extends Person{
private int score;
public void test() {
System.out.println("考试成绩 :" + score);
}
@Override
public void sleep() {
System.out.println("student sleep");
}
}
覆盖:子类重新实现父类方法,在子类中覆盖的方法可以用Override注解修饰。
super
在子类中可以用super关键字来访问父类中的实例域和方法,super和this不一样,他并不代表对象的引用,因为不能将他赋值给另一个对象变量。
@Override
public void sleep() {
//通过super访问父类中的方法。
super.eat();
System.out.println("student sleep");
}
子类构造器
在创建子类对象时,会调用子类构造器,在执行子类构造器的初始化操作之前会先调用父类构造器,当然我们也可以显示的调用父类构造器。
/**
* @author helloliu
*/
public class Person {
private String name;
private String sex;
//添加无参构造器和有参构造器
public Person() {
name = null;
sex = null;
}
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
}
public class Student extends Person{
private int score;
public void test() {
System.out.println("考试成绩 :" + score);
}
public Student() {
//显示的调用父类的无参构造器
super();
//子类初始化操作
score = 0;
}
public Student(String name, String sex, int score) {
super(name, sex);
this.score = score;
}
}
可以直接使用super调用父类的构造器,如果要在子类中显示调用父类构造器,调用语句必须是子类构造器的第一条语句。如果没有显示的调用父类构造,编译器会默认调用父类的默认构造器(无参构造),如果父类中没有默认构造器,则会出现编译错误。
final类
如果我们不希望某个类被继承,那么我们可以将这个类定义成final类,final类不允许被扩展。java类库中String类就是一个final类,不能被继承。
public final class Person {
//ToDo
}
final方法
如果只是不想类中的某个方法不能被子类覆盖,可以将这个方法定义成final方法,final类中的所有方法默认是final的,但是实例域不是final的。