继承
所有的OOP语言都会有三个特征:
- 封装(点击可跳转);
- 继承;
- 多态
为什么会有继承呢?可以先看下面的例子:
上面这两个类中的代码很相似因为它们只有最后一个方法不同其它的都相同,这样定义不但导致代码冗余而且非常麻烦。而在OOP语言中继承就是专门用来进行共性抽取,实现代码复用。
继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
在JAVA中要实现继承需要借助extends关键字。
修饰符 class 子类 extends 父类 {
// ...
}
此时我们在看再面的例子老师和学生都属于人这个大类,那么我们就可以单独定义一个People类来将他们相同的属性和方法放在一起,然后由学生类和老师类分别继承人这个大类:
class People{
public String name;
public int age;
public void speak(){
System.out.println(this.name+"正在说话");
}
}
class Teacher extends People{
public void work(){
System.out.println(this.name+"正在教书");
}
}
class Student extends People{
public void study(){
System.out.println(this.name+"正在学习");
}
}
public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.name = "zhangsan";
teacher.age = 24;
teacher.speak();
teacher.work();
System.out.println("==========");
Student student = new Student();
student.name = "xiaoming";
student.age = 15;
student.speak();
student.study();
}
}
注意:子类会将父类中的成员变量或者成员方法继承到子类中。
那么现在又有一个新问题如果子类中有和父类相同的属性或方法那系统会怎么办?
class People{
public String name;
public int age = 25;
public void speak(){
System.out.println(this.name+"正在说话");
}
}
class Teacher extends People{
public int age = 20;
public void work(){
System.out.println(this.name+"正在教书"+"今年"+this.age);
}
}
public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.name = "zhangsan";
teacher.work();
}
}
此时父类和子类都有age属性代码运行后可以看到使用的是子类的属性。
总结:
- 通过子类对象访问父类与子类中属性时,优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。
- 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
- 通过子类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;
就算父类中有private修饰的属性或方法子类也会将它继承下来但是无法访问。
super
在上面的例子中出现了一个新的关键字super。那么super关键字是干什么的?
该关键字主要作用:在子类方法中访问父类的成员。
class People{
public String name;
public int age = 25;
public void speak(){
System.out.println(this.name+"正在说话");
}
}
class Teacher extends People{
public int age = 20;
public void work(){
System.out.println(this.name+"正在教书"+"今年"+super.age);
}
}
public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.name = "zhangsan";
teacher.work();
}
}
因为父类和子类都有age属性此时如果想访问父类的属性就可以通过super关键字 (下文会为大家介绍super的第三种使用方法)。
子类的构造方法
此时如果父类有带参数的构造方法那么系统将会报错。
那没什么上面的代码可以正常执行?
原因是上面的代码使用的是系统自己默认的无参构造。那么此时应该怎么办?
接下来就为大家介绍一下super关键字的第三种使用方法:
super();
它可以调用父类的构造方法。
注:它必须放在构造方法的第一行。
如果使用的是系统自己默认的无参构造那么系统就会自动调用使用super()调用父类的无参构造。所以我们只要在子类的构造方法中调用父类的有参构造代码就不会报错了。