Java基类和派生类
背景:对基类和派生类有更清晰的认识。
从外部看来,派生类是一个与基类具有相同接口的新类,或许还会有一些额外的的方法和域 。但继承并不仅仅是类的复用。当创建了一个派生类的对象时,该类包含了一个基类的子对象。这个子对象和你用基类直接创建的对象没有什么两样。
二者的区别在于,后者来自于外部,而基类的子对象来自于派生类对象的内部。对基类的子对象初始化时至关重要的,而且也只有一种方法来保证这一点,那就是在派生类的构造器中调用基类的构造器,而基类的构造器具有执行基类初始化所需的所有能力和知识。
示例
在无参构造器时, java会自动在派生类的构造器中插入对基类的构造器的调用。
public class Humans {
Humans(){
System.out.println("我是人!");
}
}
public class Student extends Humans{
Student(){
System.out.println("我是学生!");
}
}
public class test {
public static void main(String args[]){
new Student();
}
}
输出结果为:
我是人!
我是学生!
可以发现,总是基类的构造器先被初始化。
示例
但是当构造器有参数时,那就必须使用关键字super现实地编写调用基类构造器的代码,并且匹配适当的参数列表。
public class Humans {
private String name;
Humans(String name){
System.out.println("我是叫"+name+"的人");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends Humans{
private String name;
Student(String name){
super(name);
System.out.println("我是学生!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class test {
public static void main(String args[]){
new Student("zhangsan");
}
}
输出结果:
我是叫zhangsan的人 我是学生!
如果注释掉上面的super(name);将会报错。原因是派生类必须调用基类构造器。因为实例化派生类时,基类也会被实例化,如果不调用基类的构造器,基类将不会被实例化,所以派生类没有调用基类构造器会报错。
但是如果Humans的代码变成这样就不会错。如下代码:
public class Humans {
private String name;
Humans(){
System.out.println("我是人!");
}
Humans(String name){
System.out.println("我是叫"+name+"的人");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends Humans{
private String name;
Student(String name){
//super(name);
System.out.println("我是学生!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class test {
public static void main(String args[]){
new Student("zhangsan");
}
}
输出结果为:
我是人!
我是学生!
原因是,如果基类有一个无参的构造器,就算派生类不用super显示调用基类的构造函数,编译器也会自动去调用基类的无参构造函数。
所以上面的代码不会报错,输出结果也不是
我是叫zhangsan的人
我是学生!
而是
我是人!
我是学生!
示例
派生类继承了基类的所有public和protected属性和方法,代码如下:
public class Humans {
public String sex;
protected int age ;
private String name;
Humans(String sex,String name,int age){
this.sex = sex;
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends Humans{
Student(String sex ,String name,int age){
super(sex,name,age);
}
}
public class test {
public static void main(String args[]){
Student s = new Student("男","zhangsan",10);
System.out.println(s.sex);
System.out.println(s.name);
System.out.println(s.age);
}
}
上面的System.out.println(s.name);会报错,因为name是private属性,如需访问,采用get方法:
System.out.println(s.getName())
输出结果为:
男 zhangsan 10
示例
如果派生类定义了和基类一样的属性或方法,将覆盖基类的属性和方法。如将student改为如下代码:
public class Student extends Humans{
public String sex;
protected int age ;
private String name;
Student(String sex ,String name,int age){
super(sex,name,age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
输出结果为:
null null 0
因为只有基类的属性在构造时赋值了,派生类的没有,当访问这些属性时,访问的是派生类的属性,所以全为null或者0。
只有当派生类的属性也被实例化时,才会得到属性的值。代码改为如下:
public class Student extends Humans{
public String sex;
protected int age ;
private String name;
Student(String sex ,String name,int age){
super(sex,name,age);
this.sex = sex;
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
输出结果为:
男
zhangsan
10
要注意的是,super必须在构造器的最前面,不然会报错
Java基类和派生类的更多相关文章
- 详解C++中基类与派生类的转换以及虚基类
很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...
- 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)
[源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...
- (转) C++中基类和派生类之间的同名函数的重载问题
下面有关派生类与基类中存在同名函数 fn: class A { public: void fn() {} void fn(int a) {} }; class B : public A { publi ...
- c++中基类与派生类中隐含的this指针的分析
先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...
- C++学习21 基类和派生类的赋值
在C/C++中,经常会发生数据类型转换,例如整型数据可以赋值给浮点型变量,在赋值之前,先把整型数据转换为浮点型:反过来,浮点型数据也可以赋值给整型变量. 数据类型转换的前提是,编译器知道如何对数据进行 ...
- 基类和派生类--this
基类指针在程序运行的时候的确指向的是一个派生类的对象,但指针的类型仍然是基类指针.C++是一种强类型语言,因此不能用基类指针类型的指针直接调用派生类:而且,同一个类可能有多种不同的派生类,因此不知道实 ...
- C++:基类与派生类对象之间的赋值兼容关系
4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...
- C++:基类和派生类
4.1 派生类的声明 继承实例如下: class Person{ //声明基类Person public: void print() { cout<<"name:"&l ...
- C++基类和派生类之间的转换
本文讲解内容的前提是派生类继承基类的方式是公有继承,关键字public 以下程序为讲解用例. #include<iostream> using namespace std; class A ...
随机推荐
- linux-文件数据操作awk命令
最后一列是:交互外壳 单引号里的内容不会被bash扩展 cut 同样可以做到 "\t" 制表符 cut 和 sed 结合同样可以实现 扩展:匿名方法可以有多个,and方法只能有一个 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 G. Spare Tire
这题很好啊,好在我没做出来...大概分析了一下,题目大概意思就是求 问所有满足1<=i<=n且i与m互素的ai之和 最开始我们队的做法是类似线性筛的方法去筛所有数,把数筛出来后剩下数即可, ...
- SE Springer小组之《Spring音乐播放器》需求分析说明书二
2.1 目标 Spring音乐播放器软件为课程<软件工程>所开发的课程作业,主要意图是为访问计算机中的mp3格式的音频文件,并使其能够完成访问,读取,添加,保存,播放,切换音频文件等功能. ...
- “数学口袋精灵”App的第三个Sprint计划----开发日记
一.现状 上一阶段基本完成一个小游戏,游戏具有:随机产生算式,判断对错功能.通过轻快的背景音乐,音效,给玩家提供一个良好的氛围. 二.任务认领 完成界面,基本功能后的后续任务: 冯美欣:设计&qu ...
- chrome启用flash不询问
69版本之后 打开 chrome://flags/#enable-ephemeral-flash-permission 把它从Default改为Disabled 重新打开Chrome,进入 chrom ...
- [2017BUAA软工]第零次博客作业
第一部分:结缘计算机 1. 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢?(必答) 当年高考前在专业这件事上纠结了好久,因为我对于大学各个专业具体学什么都不甚了解,于是就迟迟没有明确的目 ...
- Hadoop and net core a match made in docker
https://blog.sixeyed.com/hadoop-and-net-core-a-match-made-in-docker/
- JavaScript 模拟 HashMap例子
function map(){ var map = {}; // Map map = new HashMap(); var key = "key"; va ...
- 深度学习中 --- 解决过拟合问题(dropout, batchnormalization)
过拟合,在Tom M.Mitchell的<Machine Learning>中是如何定义的:给定一个假设空间H,一个假设h属于H,如果存在其他的假设h’属于H,使得在训练样例上h的错误率比 ...
- DELPHI XE10,JSON 生成和解析,再利用INDYHTTP控件POST
Delphi XE10,Json 生成和解析,再利用indyhttp控件Post 年09月20日 :: 阅读数: --不多说,直接上代码 procedure TFrmMain.Brand; var J ...