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

Posted 溺水的情书

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里云名师课堂Java面向对象开发54 ~ 56:继承的定义与使用相关的知识,希望对你有一定的参考价值。

继承问题的引出

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

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类)来定义时会有重复的代码,但是这个重复又没有意义。

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

继承的实现

在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()) ;
	}
}

技术图片

继承使用限制

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

调用构造方法

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

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. 继承的限制:不允许多继承,但是可以多层继承。





以上是关于阿里云名师课堂Java面向对象开发54 ~ 56:继承的定义与使用的主要内容,如果未能解决你的问题,请参考以下文章

阿里云名师课堂Java面向对象开发79 ~ 81:包装类

阿里云名师课堂Java面向对象开发74:匿名内部类

阿里云名师课堂Java面向对象开发3 ~ 6:类与对象

阿里云名师课堂Java面向对象开发3 ~ 6:类与对象

阿里云名师课堂Java面向对象开发68 ~ 7073:接口的定义和使用

阿里云名师课堂Java面向对象开发7:private实现封装处理