Java-继承-定义Student类继承于Person类(例)

我们书接上回:这一章,我们进入"继承"。

先来了解题目有关继承的需求:(本题是为知识服务,也可用于练手)

题目:

已有一个类Person类,代码如下:

Person类定义:

class Person {private String name;public Person(String name) {this.name = name;}public String getName() {return name;}//做自我介绍public void doSelfIntroduction(){System.out.println("My name is "+name);}
}

现要求定义一个类Student继承于Person类,Student类的要求如下:

  1. 新增一个成员变量 :stuID 表示学生的学号;
  2. 一个带参数构造器,初始化学生的姓名和学号;
  3. 重写父类的void doSelfIntroduction() 方法,改输出为:"My name is xxxx and my stuID is xxxx"
  4. 新增一个方法,void study(),该方法输出:"I am studying!"

Main类代码:

public class Main{public static void main(String[] args) {Person person = new Person("Tom");Scanner scanner = new Scanner(System.in);String name = scanner.next();String stuID = scanner.next();Person stu1 = new Student(name,stuID);person.doSelfIntroduction();stu1.doSelfIntroduction();Student stu2 = new Student(name,stuID);stu2.study();}
}

输入样例:

在这里给出一组输入。例如:

Jerry 121001

输出样例:

在这里给出相应的输出。例如:

My name is Tom
My name is Jerry and my stuID is 121001
I am studying!

 继承:

继承这个词,一般在语言学上:子承父业,继往开来;在生物学上也异曲同工:遗传与变异

其实,好巧不巧,java世界里面的继承也是如此道理。还记得java的核心是什么吗?类。那类在继承场景中自然而然扮演主人公——继承(java),是子类对父类属性和行为的继承

父类(superclass),子类(subclass)

继承的语法

class 子类名 extends 父类名
{//可以不再重复定义相同成员变量}

子类继承父类时,需要在类定义时,使用extends+ 父类名,表示继承关系 

继承的表现

既然继承是子类对父类属性和行为的继承——那么子类一旦继承父类,就可以拥有父类的属性和方法。这个说法确实是对的。

我们开始对这句话进行各种假设,父类是单一的吗?在继承语法上,只能extends一个直接父类。但子类的间接父类可以有很多个。就好比,人只有一个亲生父亲,却也有父亲的父亲,父亲的父亲的父亲,爷爷的爷爷的爷爷...这些间接的父类的属性和行为,子类同样也可以继承。

俩个验证

我们用代码验证

子类只允许单一继承父类:

 上面代码,我们子类单一直接继承一个父类——假如我们尝试一次性直接继承两个父类

这样:

又或者是这样: 

 

发现结果都报错了

:Class cannot extend multiple classes,不能同时继承多个父类

故:确实子类只能单一继承一个父类

验证:子类可以继承直接父类、间接父类的属性和方法:

我们写一个主类,创建三个类,Son类继承Father类,Father类继承Grandpa类

可知,在这三类的继承关系上,Grandpa类位于最高地位。

public class Grandpa {String name;//属性1:姓名int workyear;//属性2:工作年限void work()//行为1:工作{System.out.println(name + "写唐诗");}void hobby()//行为2:爱好{System.out.println(name + "君子六艺");}
}
public class Father extends Grandpa{
}//直接继承,定义类里代码为空

我们在main里验证,倘若符合子类只要extends一个父类,就可以拥有父类的属性和方法,何谓"拥有",能在主方法能对属性进行调用、赋值,对方法进行调用。

public class Main {public static void main(String[] args) {Father father = new Father();father.name = "钱";//调用对象的属性并对其进行赋值father.work();//调用对象的实例方法:工作father.hobby();//调用对象的实例方法:爱好}}

代码并没有报错,说明子类只要继承父类,即可拥有父类的属性和方法

那子类可否继承间接父类的属性和方法呢?

public class Son extends Father {}//Son类只是继承Father类,并没有定义其他属性和方法
public class Father extends Grandpa{
}//直接继承,定义类里代码为空

 主类里面:

public class Main {public static void main(String[] args) {Son son = new Son();//对类实例化son.name = "孙";//同样对姓名属性赋值son.work();//调用方法son.hobby();//调用方法}
}

看看效果: 

 

 Son类除了继承Father类没写一行,Father类如上也只继承了Grandpa类,按理说Son继承Father类,应该没有一个属性和方法。但是如上面的代码,可见,Son也继承了Grandpa的属性和两个方法——"work" 和"hobby".

我们来看看运行结果:

public class Main {public static void main(String[] args) {Grandpa grandpa = new Grandpa();grandpa.name = "赵";grandpa.work();grandpa.hobby();//创建一个grandpa的对象Father father = new Father();father.name = "钱";father.work();father.hobby();//创建一个father的对象Son son = new Son();son.name = "孙";son.work();son.hobby();//创建一个son的对象}}

 

三代可谓一脉相承,都会写唐诗和善君子六艺 。可是,这并不符合实际发展,子类为适应不断发展变化的环境和外界需求,对自身的行为和属性必须作出相应的变化和发展。

JAVA里面对这一子类进化需求,也作出回应:
1.子类可以添加父类所不具有的属性和方法

2.子类也可对继承过来的方法进行修改,但不能对属性进行修改。

再来俩个验证

1.子类可以添加父类所不具有的属性和方法

我们让Son适应时代需求,新添加一个行为和一个属性

public class Son extends Father {String[] career;//添加属性:所谓技多不压身void work2()//添加方法{System.out.println(name + "武功高强");}}
public class Main {public static void main(String[] args) {Son son = new Son();son.name = "孙";son.career = new String[]{"诗人","侠客"};//意外发现对于属性是字符串数组初始化赋值: new String[]{};son.work();son.work2();son.hobby();}}

我们在Son类添加一个新的属性和方法,在主方法里对Son 进行实例化,并对属性进行赋值和方法调用。代码没报错,可见验证假设成功

看看结果:

2.子类也可对继承过来的方法进行修改,但不能对属性进行修改。 

前半句,对继承过来的方法进行修改,我们又称——方法覆盖(Method Override)

在进行Override的时候,我们最好提前在上方加个注释:意为告诉JVM我们要对继承过来的方法进行覆盖重写了。

方法覆盖:

方法包括:

返回类型 方法名(参数列表)
{方法体
}//如果原方法还有public ,覆盖的方法也得原封不动写下来

进行方法覆盖时,为了让JVM明确我们覆盖的到底是哪个方法,返回类型和方法名(参数列表)即除了方法体可做改变,其余保持原样。(返回类型可以返回原方法的类型的子类型,该知识点涉及向上转型,咱们后面再聊) 

方法覆盖必须满足返回类型,方法名和参数列表与原方法一样。(now)

子类为了适应发展,创造出更多的属性和行为,还应该对继承下来的方法进行进化,发展出一套适合自身和外界需求的方法。——这也是传承的意义,不光为子类自身,更为整个类的发展

我们重写Father类和Son类方法work()

public class Father extends Grandpa{@Overridevoid work()//继承并覆盖Grandpa的方法{System.out.println(name + "满腹经纶,学富五车");}}
public class Son extends Father {@Override//继承间接父类的方法并进行覆盖void work(){System.out.println(name + "文能提笔安天下,武能上马定乾坤");}}

主类代码进行调用:

public class Main {public static void main(String[] args) {Grandpa grandpa = new Grandpa();grandpa.name = "赵";grandpa.work();Father father = new Father();father.name = "钱";father.work();Son son = new Son();son.name = "孙";son.work();   }}

对父类属性的修改:

JAVA本身并不提供子类“覆盖”父类成员变量的方法,子类仍然继承,但是可以不用表现,就如遗传时,基因都给子类,至于是否显现这个性状,就看子类是否愿意在主方法里面调用了。

小总结:

子类通过extends关键字,单一继承父类

子类继承直接父类和所有间接父类的属性和方法

子类可以添加新的属性和方法

子类可以改变父类的方法体

回到题目

先继承;

class Student extends Person
{}

 在子类里面添加属性:

class Student extends Person
{String stuID;
}

在子类写一个带参数构造器:

class Student extends Person
{String stuID;
}
public Student(String name,String stuID)
{this.name = name;//真的是这样赋值吗this.stuID = stuID;}//带参数构造器

我们发现报错了

 父类里面的name成员是private,子类不能公开访问,那子类拥有这个属性吗?答案是有的。但是不能公开访问,需要其他方式进行访问。

我们再看父类代码,发现父类的构造器是公开的:父类是这个属性的创始者,对于这个属性虽然是私有的,子类蛮干是无法访问的。但是父类也为我们公开了访问和使用的方法,扑面而来的哲学气息:授人以鱼不如授人以渔。

鱼,父类已经暗暗给你,不过需要你学会如何渔。

super关键字

还记得父类的英文名吗?superclass,super关键字就是调用父类的方法,实现当前方法的需求。

方便理解,我们可以把super替换成父类的名字。

那么在子类里面要初始化从父类继承过来的私有属性,需要调用父类的构造器,怎么用super来写呢?答案已经呼之欲出了对不对

super()是调用父类的无参构造器,super(参数1,参数...)是调用父类的有参构造器,super.方法名是调用父类的方法。特殊说明,调用父类的构造器我们一般选用super关键字且在第一行,而其他公开实例方法,this和super都可以:his是因为子类直接继承过来了,super也可以:在子类里面使用父类的方法完成当前对象的需求

同样的,这里的父类可以是间接父类。

class Student extends Person
{String stuID;public Student(String name,String stuID){super(name);//调用父类的构造器一定是在子类的第一行this.stuID = stuID;}
}

对父类方法的重写:

class Student extends Person
{//...@Overridepublic void doSelfIntroduction(){System.out.println("My name is " + getName() + " and my stuID is " + stuID);}//getName()前面默认省掉this,也可用super,结果是一样的
}

 

 在子类里面新增一个方法:
 

class Student extends Person
{
//...public void study(){System.out.println("I am studying!");}//新增方法
}

完整代码参考:
 

class Student extends Person
{String stuID;public Student(String name,String stuID){super(name);this.stuID = stuID;}@Overridepublic void doSelfIntroduction(){System.out.println("My name is " + getName() + " and my stuID is " + stuID);}public void study(){System.out.println("I am studying!");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/591649.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Swing中的FlowLayout/WrapLayout在打横排列时候如何做到置顶对齐

前言 最近在开发swing客户端时候碰到一个棘手的问题: Swing中的FlowLayout/WrapLayout在打横排列时候如何做到置顶对齐如果是vue或者react,一搜百度什么都出来了,swing的话,嗯。。。资料有点少而且大部分是stack overflow上面的…

Java 7、Java 8常用新特性

目录 Java 8 常用新特性1、Lambda 表达式2、方法引用2.1 静态方法引用2.2 特定对象的实例方法引用2.3 特定类型的任意对象的实例方法引用2.4 构造器引用 3、接口中的默认方法4、函数式接口4.1 自定义函数式接口4.2 内置函数式接口 5、Date/Time API6、Optional 容器类型7、Stre…

若依框架mysql 搜索中文等于不生效

背景&#xff0c;字段存储的是中文 不生效代码如下 <if test"constellation ! null and constellation ! ">AND u.constellation #{constellation}</if> 正确生效的代码如下 <if test"constellation ! null and constellation ! ">A…

C语言:动态内存管理(二)

目录 前言 1.3 realloc​编辑 3、常见动态内存管理错误 3.1 对空指针的解引用操作 3.2 对动态开辟的空间进行越界访问 3.3 对非动态开辟内存使用free释放 3.4 使用free释放一块动态内存开辟的一部分 3.5 对同一块空间的多次释放 3.6 动态内存开辟之后忘记释放 总结 前…

【Qt 学习笔记】按钮实现helloworld | 信号与槽概述

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 按钮实现helloworld | 初识信号与槽 文章编号&#xff1a;Qt 学习笔记…

C#.net6.0手术麻醉信息管理系统源码,智慧手术室管理平台源码

手术麻醉信息管理系统源码&#xff0c;自主版权的手麻系统源码 手术麻醉信息管理系统包含了患者从预约申请手术到术前、术中、术后的流程控制。手术麻醉信息管理系统主要是由监护设备数据采集子系统和麻醉临床系统两个子部分组成。包括从手术申请到手术分配&#xff0c;再到术前…

Android Studio学习9——使用Logcat打印日志

在Android开发中&#xff0c;Logcat是一个工具&#xff0c;它允许开发者查看设备或模拟器的日志信息。开发者可以使用Log类来打印日志信息&#xff0c;这对于调试和错误排查非常有帮助。 v 或 verbose: 最低等级&#xff0c;显示所有消息。d 或 debug: 用于调试消息。i 或 info…

【剑指offr--C/C++】JZ31 栈的压入、弹出序列

一、题目 二、思路及代码 借助一个辅助栈来模拟入栈过程&#xff0c; ①在入栈之前先判断当前要入栈的元素是否与出栈数组当前元素相同&#xff0c; ② 如果不相同就入栈&#xff1b; ③如果相同就不用入栈了&#xff08;不入栈出栈&#xff09;&#xff0c;然后再依次取出栈的…

计算机网络-从输入网址到访问网站的全过程

当我们在浏览器中输入一个网址并按下回车键时&#xff0c;会发生一系列复杂的过程&#xff0c;最终使我们能够看到网页的内容。以下是这个过程的详细步骤&#xff1a; 客户端&#xff1a;首先&#xff0c;用户在浏览器中键入网址&#xff0c;然后浏览器会根据这个网址生成一个H…

Jenkins 持续集成 【CICD】

持续集成 &#xff08;Continuous integration&#xff0c;简称CI&#xff09; 持续集成是一种开发实践&#xff0c;它倡导团队成员频繁的集成他们的工作&#xff0c;每次集成都通过自动化构建&#xff08;包括编译、构建、打包、部署、自动化测试&#xff09;来验证&#xff…

element-ui breadcrumb 组件源码分享

今日简单分享 breadcrumb 组件的源码实现&#xff0c;主要从以下三个方面&#xff1a; 1、breadcrumb 组件页面结构 2、breadcrumb 组件属性 3、breadcrumb 组件 slot 一、breadcrumb 组件页面结构 二、breadcrumb 组件属性 2.1 separator 属性&#xff0c;分隔符&#xff…

Web Animations API 动画

Element.animate() dom.animate动画可以避免污染dom原有的css动画 参考资料 Element.animate() - Web API 接口参考 | MDN Element: getAnimations() method - Web APIs | MDN .tunnel{width:200px;height:200px;background-color:#38f;}<div class"tunnel" …