阿里云【名师课堂】Java面向对象开发54 ~ 56:继承的定义与使用

@

54:继承问题的引出

面向对象编程的三大特点:封装、继承、多态,继承就是在已经有基础上进行对功能的扩充。
如果要更好的理解为什么要有继承,下面用之前学习的概念定义两个类:学生
范例:定义人类:姓名年龄,学生类:姓名年龄学校

class Person {
	private String name ;
	private int age ;
	
	public void setName(String name){
		this.name = name ;
	}
	public String getName(){
		return this.name ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public int getAge(){
		return this.age ;
	}
}

class Student {
	private String name ;
	private int age ;
	private String school ;
	
	public void setName(String name){
		this.name = name ;
	}
	public String getName(){
		return this.name ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public int getAge(){
		return this.age ;
	}
	public void setSchool(String school){
		this.school = school ;
	}
	public String getSchool(){
		return this.school ;
	}
}

学生类只比人类多了一个属性。仔细观察程序,按照之前的模式(单独的简单Java类)来定义时会有重复的代码,但是这个重复又没有意义。

  • 因为从概念上说,学生一定是人,学生的范围比人小,描述的属性、方法比人多。所以学生应该是人的扩充。

55:继承的实现

在Java中继承使用extends关键字实现。定义语法如下:

  • class 子类 extends 父类 {}
    • 子类也称派生类,父类也称超类(super class)

范例:继承的基本实现

class Person {
	private String name ;
	private int age ;
	
	public Person() {} // 注意要有一个无参构造
	
	public void setName(String name) {
		this.name = name ;
	}
	public String getName() {
		return this.name ;
	}
	public void setAge(int age) {
		this.age = age ;
	}
	public int getAge() {
		return this.age ;
	}
}

class Student extends Person { // 暂时不做任何定义
}

public class TestDemo {
	public static void main(String args[]) {
		Student stu = new Student() ; // 子类实例化对象
		stu.setName("dexter") ; // 子类中并没有此属性、方法
		stu.setAge(20) ; // 子类中并没有此属性、方法
		System.out.println("name:" + stu.getName() + ",age:" + stu.getAge()) ;
	}
}

在这里插入图片描述
通过代码可以发现,当发生了继承之后,子类可以直接继承父类,可以实现代码的重用,并且子类最低也保持和父类相同的功能,想要扩充属性和方法只要在子类中直接操作。
范例:子类进行功能扩充

······  // Person类没有任何改变
class Student extends Person {
	private String school ;
	
	public void setSchool(String school){
		this.school = school ;
	}
	public String getSchool(){
		return this.school ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Student stu = new Student() ; // 子类实例化对象
		stu.setName("dexter") ; // 子类中并没有此属性
		stu.setAge(20) ; // 子类中并没有此属性
		stu.setSchool("hfut") ;
		System.out.println("name:" + stu.getName() + ",age:" + stu.getAge() + ",school:" + stu.getSchool()) ;
	}
}

在这里插入图片描述

56:继承使用限制

虽然继承可以实现子类共享父类的属性、方法,但是继承也有一些限制:

调用构造方法

子类对象在实例化之前是先自动实例化父类对象的,调用父类的构造方法后再进行子类对象的实例化。

class Person {
	public Person() {
		System.out.println("*** Person类对象创建 ***") ;
	}
}

class Student extends Person {
	public Student() {
		System.out.println("*** Student类对象创建 ***") ;
	}
}

public class ExtendsDemo {
	public static void main(String args[]) {
		new Student() ; // 子类实例化对象
	}
}

可以看到,虽然没有任何一条语句调用了父类构造,但是父类构造还是被执行了,说明子类对象的实例化之前一定要先实例化其父类对象。

  • 注意:此时在子类构造的首行中(因为调用父类构造方法,一定在第一句)有一条隐含语句:super() ;,此语句在构造无参时写与不写都一样;
  • 而父类没有无参构造时子类构造中一定要有super(想要调用的父类构造的对应参数) ;,否则会有错误提示:实际参数列表和形式参数列表长度不同
class Person {
	public Person(String name, int age) {
		System.out.println("*** Person类对象创建 ***") ;
	}
}

class Student extends Person {
	public Student(String name, int age, String school) {
		super(name,age) ;
		System.out.println("*** Student类对象创建 ***") ;
	}
}

public class ExtendsDemo {
	public static void main(String args[]) {
		new Student("dexter",20,"hfut") ; // 子类实例化对象
	}
}

单继承:一个子类只能继承一个父类

范例:Java中错误的继承:多继承

class A {}
class B {}
class C extends A,B {}

多继承的目的是C类同时继承A类、B类中的操作,而Java不允许多继承,想要达到这个目的可以采用: 多层继承

class A {}
class B extends A {}
class C extends B {}

但是多层继承不建议过多层。

子类继承父类的所有结构

所有结构:私有属性、构造方法、普通方法。
所有的非私有操作属于显式继承,所有的私有操作属于隐式继承

  • 显示继承:可以直接调用
  • 隐式继承:通过其他方式调用(settergetter
class Person {
	private String name ;
	
	public Person() {}
	
	public void setName(String name) {
		this.name = name ;
	}
	public String getName() {
		return this.name ;
	}
}

class Student extends Person {
	
}

public class ExtendsDemo {
	public static void main(String args[]) {
		Student stu = new Student() ;
		stu.setName("dexter") ;
		System.out.println(stu.getName()) ;
	}
}
// 输出dexter

而如果想要在子类中直接调用name会发生:

class Student extends Person {
	public void method() {
		System.out.println(name) ;
	}
}
// 输出错误提示:name 在 Person 中是 private 访问控制

父类中的属性的确被子类所继承,但是可以发现子类能够使用的只是所有的非private操作(public),而所有的private操作肯定无法直接使用,所以称其为隐式继承。

总结

  1. 继承的语法,继承的目的:扩展已有类的功能,使代码重用;
  2. 子类实例化对象的流程:无关如何操作一定都是先实例化父类,而后再实例化子类对象。
  3. 继承的限制:不允许多继承,但是可以多层继承。
posted @ 2020-06-14 11:28  溺水的情书  阅读(148)  评论(0编辑  收藏  举报