java核心技术:继承
继承是一种类之间的关系,他描述了类之间一种“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的。