菜鸡的Java笔记 第十九 - java 继承
继承性的主要目的,继承的实现,继承的限制
继承是面向对象中的第二大主要特点,其核心的本质在于:可以将父类的功能一直沿用下去
为什么需要继承?
那么为了更好的区分出之前学习的概念与现在程序的区别,下面通过两个具体的代码来进行研究
例如:现在有俩个类:Person,Student,按照原始的方式,程序代码实现如下:
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{
private String name;
private int age;
private String school;
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void setSchool(String school){
this.school = school;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public String getSchool(){
return this.school;
}
}
public class inherit{
public static void main(String args[]){
System.out.println();
}
}
两个类出现有重复,而且最为关键的问题是学生从现实的角度来看一定是个人
那么按照这样的理解就可以发现出现重复的核心问题所在了,就是两个类之间没有联系
之前所编写的代码或者说之前所学习到的概念那么还不足以解决多个类之间的代码重复消除问题
Student 是比 Person 更加细化的定义范畴
使用继承解决问题
在java中可以利用继承的概念来实现父类代码的重用问题,程序中可以使用extennds 关键字实现继承操作的定义
其使用的语法如下:
class 子类 extends 父类{}
需要注意点名词概念:
子类:也被称为派生类
extends虽然从本质上来讲属于继承概念,但是其翻译为扩展,扩充的意思
父类 本质上在java中称为超类(Super Class)
范例:继承的基本使用
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 是Person 的子类
// 此时并没有在Student类里面定义任何的操作
}
public class inherit{
public static void main(String args[]){
Student stu = new Student();// 实例化子类对象
stu.setName("少爷");//通过Person类继承而来
stu.setAge(20);//通过Person类继承而来
System.out.println("姓名:"+stu.getName+",年龄:"+stu.getAge());
}
}
/*
结果
姓名:少爷,年龄:20
*/
通过以上的程序就可以发现一点:子类在继承了父类之中,那么对于父类的支持方法不会减少
但是子类可以进一步扩充属于自己的属性与方法
范例:继承的基本使用
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 是Person 的子类
private String school; // 子类自己扩充的属性
public void setSchool(String school){
this.school = school;
}
public String getSchool(){
return this.school;
}
public class inherit{
public static void main(String args[]){
Student stu = new Student();// 实例化子类对象
stu.setName("少爷");//通过Person类继承而来
stu.setAge(20);//通过Person类继承而来
stu.setSchool("清华");//子类自己扩充的属性
System.out.println("姓名:"+stu.getName+",年龄:"+stu.getAge()+",学校:"+stu.getSchool());
}
}
/*
结果
姓名:少爷,年龄:20,学校:五道口
*/
通过这样的继承实现发现:
父类的功能可以延续到子类继续使用,这样在某些父类不能够修改的情况下,就可以通过继承来实现功能的扩充
子类中至少可以维持父类的原始方法不变,也就是说在子类里面父类的方法功能不会减少
*/
/* 继承的使用限制
虽然继承的核心目的在于扩充类中的已有功能,但是在实际的开发之中,继承的使用也是存在有诺干限制的,这些限制必须注意
限制一:java不允许多重继承,也就是说一个子类只能够继承一个父类
因为C++它支持多继承,也就是说一个子类可以同时继承多个父类
范例:错误代码
class A{
}
class B{
}
class C extendsa A,B{
}
public class inherit{
public static void main(String args[]){
System.out.println();
}
}
那么为什么实际中会出现这种代码呢?
其实本质上也只是希望C类可以同时继承A,B类的方法,但是由于这样的做法与现实生活有冲突,所以从java的角度就屏蔽了,但是有解决方案
虽然java不允许多重继承,但是却允许多层继承,以下代码为方案:
class A{
}
class Bextendsa A{
}
class C extendsa B{
}
public class inherit{
public static void main(String args[]){
System.out.println();
}
}
此时的C类实际上就具备有A,B类的全部定义,但是从实际的开发,这种继承的层次关系不要超过三层
限制二:子类在继承父类之后会将父类中的全部结构继承下来,但是对于私有的操作属于隐式继承(子类不能直接调用),而所有的非私有操作属于显式继承(可以直接调用)
范例:观察显式继承
class A{
private String name:
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
class B extendsa A{
}
public class inherit{
public static void main(String args[]){
B b= new B();
b.setName("少爷");
System.out.println(b.getName());
}
}
现在对于子类B而言是存在name属性的,但是这个属性子类并不能够直接操作
范例:子类B直接访问
class A{
private String name:
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
class B extendsa A{
public void print(){
System.out.println(name);
}
}
public class inherit{
public static void main(String args[]){
B b= new B();
b.setName("少爷");
System.out.println(b.getName());
}
}//结果程序出错
也就是说此时的name属于隐式继承,而所有的setter方法属于显式继承,显式继承可以直接调用,而隐式继承的只能够间接的操作或者不能够操作
限制三:在实例化子类对象时会默认调用子类的无参构造方法,但是在执行子类构造前会首先自动实例化父类构造为父类的对象实例化,也就是说父类对象永远早于子类对象的实例化
范例:观察实例化过程
class A{
public A(){
System.out.println("***********************");
}
}
class B extends A{
public B(){
System.out.println("###########################");
}
}
public class inherit{
public static void main(String args[]){
B b= new B();
}
}
/*
结果:
***********************
###########################
*/
如果说现在非要为子类加上一个调用父类构造的标记,那么就可以使用“super()”的形式完成
class A{
public A(){
System.out.println("***********************");
}
}
class B extends A{
public B(){
super(); // 表示由子类构造调用父类构造
System.out.println("###########################");
}
}
public class inherit{
public static void main(String args[]){
B b= new B();
}
}
/*
结果:
***********************
###########################
*/
也就是证明,在子类的构造之中其实一直隐藏了一行“super()”语句,但是在进行无参父类构造调用的时候,写上“super()”是没有意义的
往往是在父类没有提供无参构造时使用的
范例:错误代码
class A{
public A(String name){
System.out.println("***********************");
}
}
class B extends A{
public B(){
// super(); // 表示由子类构造调用父类构造
System.out.println("###########################");
}
}
public class inherit{
public static void main(String args[]){
B b= new B();
}
}//结果程序出错
这个时候很明显使用隐含的“super()”并不合适,所以应该明确的调用指定参数的构造方法
class A{
public A(String name){
System.out.println("***********************");
}
}
class B extends A{
public B(String name){
super(name); // 表示由子类构造调用父类构造
System.out.println("###########################");
}
}
public class inherit{
public static void main(String args[]){
B b= new B("少爷");
}
}
在大多数情况下父类一般都会提供有无参构造方法,这个时候可以在子类构造中不出现“super()”的语句
但是如果此时父类没有提供无参构造方法,那么子类就必须使用“super()”调用指定参数的构造方法
对于 super 调用构造方法的情况需要注意如下几项:
不管你子类怎么折腾都一定要去调用父类的构造方法,即:调用父类构造使用 super()
super() 是在子类中编写的,表示通过子类的构造方法去调用父类构造,必须放在子类构造方法的首行,不能与“this()”不能同时出现在构造方法之中,两者关系属于二选一
如果现在父类中没有提供无参构造方法,那么在子类构造之中必须明确的调用有参构造方法,必须使用 super 调用指定参数的父类构造
this 是应用在本类的关键字,而 super 是应用在子类中的关键字,利用 super 找到父类结构
分析:关于this()与super()的问题
在之前学习过this()表示调用本类的其他构造方法,而现在有了继承关系之后,可以使用super() 由子类调用父类中指定的构造方法,并且这两个语句都一定要出现在首行,也就是说这两个语句不能同时出现
范例:不让子类调用父类的构造
class A{
public A(String name){
System.out.println("***********************");
}
}
class B extends A{
public B(){
}
public B(String name){
this();//
System.out.println("###########################");
}
}
public class inherit{
public static void main(String args[]){
B b= new B("少爷");
}
}
在子类的构造方法中出现了“this()”,这样就不会出现“super()”的默认执行而转为调用本类的构造方法了
那么这样是不是可以不调用父类构造了呢?
总结
1.继承的唯一好处就是进行了功能的扩充,并且java只支持单继承局限
2.子类对象实例化时一定要先实例化父类对象,而后在实例化子类自己的对象
*/
菜鸡的Java笔记 第十九 - java 继承的更多相关文章
- 菜鸡的Java笔记 第二十九 - java 单例设计模式
SingleCase 单例设计模式 1.单例设计模式的特点 2.多例设计模式的特点 内容 单例设计模式 现在如果说有这么一个程序类 class S ...
- Java进阶(三十九)Java集合类的排序,查找,替换操作
Java进阶(三十九)Java集合类的排序,查找,替换操作 前言 在Java方向校招过程中,经常会遇到将输入转换为数组的情况,而我们通常使用ArrayList来表示动态数组.获取到ArrayList对 ...
- 菜鸡的Java笔记 第二十八 - java 包的定义
包的主要作用以及定义 包的导入操作 系统常见的开发包 jar 程序命令 包的定义 在任何的操作系统之中都有一个统一的共识:同一个目录下不能够存在有相同的文 ...
- Java笔记(二十九)……网络编程
概述 网络模型 网络通讯的要素 ip地址:网络中设备的标识符 端口:用于标识同一台设备上不同的进程,有效端口:0~65535,其中0~1024是系统使用端口或者保留端口 TCP与UDP UDP特点: ...
- 菜鸡的Java笔记 第二十六 - java 内部类
/* innerClass 从实际的开发来看,真正写到内部类的时候是在很久以后了,短期内如果是自己编写代码,几乎是见不到内部类出现的 讲解它的目的第一个是为了解释概念 ...
- 菜鸡的Java笔记 第二十四 - java 接口的基本定义
1.接口的基本定义以及使用形式 2.与接口有关的设计模式的初步认识 3.接口与抽象类的区别 接口与抽象类相比,接口的使用几率是最高的,所有的 ...
- 菜鸡的Java笔记 第二十二 - java 对象多态性
本次只是围绕着多态性的概念来进行讲解,但是所讲解的代码与实际的开发几乎没有关系,而且多态一定是在继承性的基础上才可以操作的, 而本次将使用类继承的关系来描述多态的性质,实际的开发中不会出 ...
- 菜鸡的Java笔记 第十八 - java 代码块
代码块 code block content (内容) 在程序结构之中使用"{}"定义的内容就称为代码块,但是会根据其声明的位置以及关 ...
- 菜鸡的Java笔记 第十六 - java 引用传递
referenceDelivery 引用传递是整个java 的精髓,也是所有初学者最难学的地方 引用的本质:同一块堆内存可以被不同的栈内存所指向 下面通过三道程序来进行引用传 ...
随机推荐
- ElasticJob 3.0.0:打造面向互联网生态和海量任务的分布式调度解决方案
ElasticJob 于 2020 年 5 月 28 日重启并成为 Apache ShardingSphere 子项目.新版本借鉴了 ShardingSphere 可拔插架构的设计理念,对内核进行了大 ...
- codeforces316E3 Summer Homework(线段树,斐波那契数列)
题目大意 给定一个n个数的数列,m个操作,有三种操作: \(1\ x\ v\) 将\(a_x\)的值修改成v $2\ l\ r\ $ 求 \(\sum_{i=l}^r x_i*f_{i-l}\) 其中 ...
- Kubernetes-Service介绍(三)-Ingress(含最新版安装踩坑实践)
前言 本篇是Kubernetes第十篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战. Kubernetes系列文章: Kubernetes介绍 Kubernetes环境搭建 Kuberne ...
- ES2020新特性记录
1.可选链操作符 // oldlet ret = obj && obj.first && obj.first.second// newlet ret = obj?.fi ...
- 项目实战:Qt文件改名工具 v1.2.0(支持递归检索,搜索:模糊匹配,前缀匹配,后缀匹配;重命名:模糊替换,前缀追加,后缀追加)
需求 在整理文件和一些其他头文件的时候,需要对其名称进行整理和修改,此工具很早就应该写了,创业后,非常忙,今天抽空写了一个顺便提供给学习. 工具和源码下载地址 本篇文章的应用包和源码包可在 ...
- 【Java虚拟机4】Java内存模型(硬件层面的并发优化基础知识--缓存一致性问题)
前言 今天学习了Java内存模型第一课的视频,讲了硬件层面的知识,还是和大学时一样,醍醐灌顶.老师讲得太好了. Java内存模型,感觉以前学得比较抽象.很繁杂,抽象. 这次试着系统一点跟着2个老师学习 ...
- MySQL:补充知识
MySQL补充知识 在学习完 MySQL 基础与提高内容后: 基础知识笔记: MySQL:基础语法-1 MySQL:基础语法-2 MySQL:基础语法-3 MySQL:基础语法-4 提高知识笔记: M ...
- 2020BUAA软工结伴项目作业
2020BUAA软工结伴项目作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结伴项目作业 我在这个课程的目标是 学 ...
- 单片机I/O口推挽与开漏输出详解(力荐)
推挽输出:可以输出高,低电平,连接数字器件;推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止. 开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电 ...
- 万维网www与HTTP协议
文章转自:https://blog.csdn.net/weixin_43914604/article/details/105901440 学习课程:<2019王道考研计算机网络> 学习目的 ...