专业编程基础技术教程

网站首页 > 基础教程 正文

【继承的定义和使用】Java中的继承,让你的代码更高效、可重用!

ccvgpt 2024-07-28 12:23:06 基础教程 7 ℃

“这里是云端源想IT,帮你轻松学IT”

嗨~ 今天的你过得还好吗?

【继承的定义和使用】Java中的继承,让你的代码更高效、可重用!

倘若心中愿意

道路千千条

倘若心中不愿意

理由万万个

- 2023.08.28 -


继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

Java是一门强大的编程语言,它为程序员提供了许多强大的功能,其中之一就是继承。在本文中,我们将深入探讨Java中的继承,并了解如何使用它来创建高效、可重用的代码。



一、继承的概念

继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。Java继承是使用已存在的类定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。

继承(inheritance) 还原客观世界中的is a关系


is a 关系

比如:

柠檬 是一种 水果(苹果 is a 水果)

山竹 是一种 水果(山竹 is a 水果)

狗 是一种 动物 (狗 is a 动物)

机械键盘 是一种 键盘(机械键盘 is a 键盘)

is a关系的特点:前者一定具备后者的特征与行为,可以简单的理解,子类可以看作是对父类的扩展。

计算机中的is a关系

特点:

  • 计算机中的is a 关系称为继承关系,是一种类与类之间的关系。
  • 前者称为父类、基类或超类,后者称为子类或派生类。
  • 当继承关系建立时,子类也能拥有父类中的特征(属性)与行为(方法)。


继承的关键字:extends

语法格式:

class 子类名 extends 父类名{
...
}


继承的好处:

  • 提高了代码的复用性,解决了代码臃肿的问题;
  • 它是多态的前提。(多态的前提是必须有继承关系)


继承的特点:

  • 子类继承父类,是继承了父类所有的东西(成员变量、成员方法包括私有方法),但是子类不能使用私有的东西,只能通过父类的公共的访问间接的让子类访问它。
  • 在Java中,继承只支持单继承,不支持多继承(子类名 extends 父类名1,父类名2,...)

但是,Java是可以支持多层继承的。

类和类之间的关系:继承关系

类和接口之间的关系:实现关系


二、继承的分类

继承分为单继承和多继承,Java语言只支持类的单继承,但可以通过实现接口的方式达到多继承的目的。我们先用一张表概述一下两者的区别,然后再展开讲解。

单继承

单继承,是一个子类只拥有一个父类,如我们上面讲过的Animal类和它的子类。单继承在类层次结构上比较清晰,但缺点是结构的丰富度有时不能满足使用需求。


多继承(Java不支持,但可以实现)

多继承,是一个子类拥有多个直接的父类。这样做的好处是子类拥有所有父类的特征,子类的丰富度很高,但是缺点就是容易造成混乱。下图为一个混乱的例子。

Java虽然不支持多继承,但是Java有三种实现多继承效果的方式,分别是内部类、多层继承和实现接口。


内部类:内部类可以继承一个与外部类无关的类,保证了内部类的独立性,正是基于这一点,可以达到多继承的效果。


多层继承:子类继承父类,父类如果还继承其他的类,那么这就叫多层继承。这样子类就会拥有所有被继承类的属性和方法。

实现接口:实现接口无疑是满足多继承使用需求的最好方式,一个类可以实现多个接口满足自己在丰富性和复杂环境的使用需求。类和接口相比,类就是一个实体,有属性和方法,而接口更倾向于一组方法。


举个例子,就拿斗罗大陆的唐三来看,他存在的继承关系可能是这样的:

所以,通过实现接口就能够满足我们的Java中多继承的使用需求啦!


三、继承的实现

如果在Java程序之中要想实现继承关系,那么就必须依靠extends关键字来完成。

class 子类 extends 父类 { }

特别需要注意的是,很多情况下会把子类称为派生类,把父类称为超类(SuperClass)


范例:观察继承的实现

class Person {
private String name ;
private int age ;
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
}
class Student extends Person { // Student是子类
// 在子类之中补丁已任何的功能
}
public class StringDemo {
public static void main(String args[]){
Student stu = new Student() ;
stu.setName("林大强") ; // 父类定义
stu.setAge(38) ; // 父类定义
System.out.println("姓名:" + stu.getName() + "、年龄:" + stu.getAge()) ;
}
}

由于此时存在有继承关系,所以此时的子类即便没有任何的操作,那么也可以直接通过父类继承而来的功能,这个时候内存关系如下:并没有变化

继承实现的主要目的是在于子类可以重用父类中的结构,并且也可以实现功能的扩充,那么同时强调了:子类可以定义更多的内容,并且描述的范围更小。

范例:子类扩充定义

class Person {
private String name ;
private int age ;
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
}
class Student extends Person { // Student是子类
// 在子类之中补丁已任何的功能
private String school; // 子类扩的属性
public void setSchool(String school){
this.school = school ;
}
public String getSchool(){
return this.school ;
}
}
public class StringDemo {
public static void main(String args[]){
Student stu = new Student() ;
stu.setName("林大强") ; // 父类定义
stu.setAge(38) ; // 父类定义
stu.setSchool("加里敦大学") ;
System.out.println("姓名:" + stu.getName() + "、年龄:" + stu.getAge() + "、学校:" + stu.getSchool()) ;
}
}

如果此时继续讨论内存关系,则就会出现两个范围的属性了(Person()父类范畴、Student子类范畴)


子类对象实例化流程

现在已经成功的实现了继承关系,但是一旦程序之中提供有继承逻辑,那么对于子类的对象的实例化定义是由要求的。从正常的社会逻辑来讲:没有父亲就没儿子,对于继承程序的逻辑也是一样的,在你进行子类逻辑实例化对象的时候,首先一定要实例化好父类对象。


范例:观察一个程序

class Person {
public Person(){
System.out.println("【Person父类】一个新的Person父类实例化对象产生了") ;
}
}
class Student extends Person { // Student是子类
public Student(){ //构造方法
System.out.println("【Student子类】一个新的Student实例化对象产生了。") ;
}
}
public class StringDemo {
public static void main(String args[]){
new Student() ; // 实例化子类对象
}
}

现在即使没有进行父类对象实例化,也会由系统自动调用父类的构造方法(实例化父类对象),默认情况下的子类对象实例化流程会自动实例化父类对象。实际上这个时候就相当于子类的构造方法里面隐含了一个“super()”的形式。


范例:修改子类定义

class Person {
public Person(){
System.out.println("【Person父类】一个新的Person父类实例化对象产生了") ;
}
}
class Student extends Person { // Student是子类
public Student(){ //构造方法
super() ; // 写与不写语句效果一样
System.out.println("【Student子类】一个新的Student实例化对象产生了。") ;
}
}
public class StringDemo {
public static void main(String args[]){
new Student() ; // 实例化子类对象
}
}

super()表示的就是子类构造调用父类构造的语句,该语句只允许放在子类构造方法的首行。在默认情况选,子类只会调用父类中的无参构造方法,所以写与不写“super()”区别不大,但是如果说你的父类里面没有提供无参构造,这个时候就必须利用super()明确构造有参构造。

class Person {
private String name ;
private int age ;
public Person(String name, int age){
this.name = name ;
this.age = age ;
}
}
class Student extends Person { // Student是子类
private String school ;
public Student(String name, int age, String school){ // 构造方法
super(name,age) ; // 明确调用父类构造
this.school = school ;
}
}
public class StringDemo {
public static void main(String args[]){
new Student("林小强", 48, "北京大学") ; // 实例化子类对象
}
}

无论如何折腾,在实例化子类对象的同时一定会实例化父类对象,目的是为了所有的属性可以进行空间分配。

super与this都可以调用构造方法,super是由子类调用父类的构造,而this是调用本类构造,并且一定要放在首行,所以两个语句不允许同时出现。


四、继承定义注意事项

现在已经清楚了整个继承逻辑,那么下面对于继承实际上还有一些要求。

1、Java之中不允许多重继承,只允许多层继承。

错误的继承(多重继承):

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


多层继承:

class A {}
class B extends A {}
class C extends B {} // 多层继承

继承的主要目的是扩展已有类的功能,但是多重继承目的是希望可以同时继承多个类中的方法,而面对于多继承的要求应该将范围限定在同一类之中。如果说现在使用了多层继承,这个时候对于C类同样可以继承多个父类的操作,但是多层继承也应该有一个限度,千万别整个祖宗十八代,对于继承关系而言,如果是你写的代码,理论上层次不应该超过三层。



2、在进行继承关系定义的时候,实际上子类可以继承父类中的所有操作结构。但是对于私有操作属于隐式继承,而所有的非私有操作属于显式继承。

class Person {
private String name ;
public void setName(String name) {
this.name = name ;
}
public String getName(){
return this.name ;
}
}
class Student extends Person {
public Student(String name){
setName(name) ; // 设置name属性内容
}
public void fun() {
//System.out.println(name) ; // 直接访问不可以,因为是私有的
System.out.println(getName()) ; // 间接访问
}
}
public class StringDemo {
public static void main(String args[]){
Student stu = new Student("林中强") ;
stu.fun() ;
}
}

继承一旦发生了,所有的操作就都可以被子类使用了,并且在程序设计里面并没有考虑到现实生活中所谓的“败家子”的概念,子类至少会维持父类的现有功能。



总结:继承是面向对象编程中的一个重要概念,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。通过继承,子类可以重用父类的代码,并且可以在不修改父类的情况下添加自己的特定功能。


我们下期再见!


END

文案编辑|云端学长

文案配图|云端学长

内容由:云端源想分享


Tags:

最近发表
标签列表