菜鸡的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 的精髓,也是所有初学者最难学的地方 引用的本质:同一块堆内存可以被不同的栈内存所指向 下面通过三道程序来进行引用传 ...
随机推荐
- ORACLE 坏块的模拟和查看
坏块的模拟和查看使用bbed工具修改数据文件的块,然后使用dbv和rman工具查看坏块. 1.创建数据:根据dbv查看没有坏块Total Pages Marked Corrupt : 0create ...
- caffe转换变量时的gflags问题
先解决错误7,解决方式来自于http://blog.csdn.net/wishchin/article/details/51888566这篇博文,感谢博主 只需要添加上 #pragma comment ...
- 活动回顾|ShardingSphere X openGauss,将会产生怎样的化学反应?
"ShardingSphere 作为 openGauss 生态的开源分布式数据库解决方案,将持续助力于 openGauss,满足千行百业广大客户分布式场景需求." 5月29日,由 ...
- 运用shapefile.js解析Shp文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...
- Visual Studio CMake 项目和 WSL
Visual Studio CMake 项目和 WSL https://devblogs.microsoft.com/cppblog/c-with-visual-studio-2019-and-win ...
- nexus设置npm下载管理
nexus设置npm下载管理 第一步 登录私服网页 第二步 创建存储空间(如果使用默认的存储空间,此步骤可省略) 第三步 输入空间的名称,点击create创建 第四步 创建仓库 npm的仓库有三种: ...
- 【UE4 C++】 获取Actor、Controller、Pawn、Character
获取 Actor TActorIterator 遍历 可以用于遍历 Actor,也可以用于遍历 Component for (TActorIterator<AStaticMeshActor> ...
- 康托展开+逆展开(Cantor expension)详解+优化
康托展开 引入 康托展开(Cantor expansion)用于将排列转换为字典序的索引(逆展开则相反) 百度百科 维基百科 方法 假设我们要求排列 5 2 4 1 3 的字典序索引 逐位处理: 第一 ...
- 机器学习:EM算法
EM算法 各类估计 最大似然估计 Maximum Likelihood Estimation,最大似然估计,即利用已知的样本结果,反推最有可能(最大概率)导致这样结果的参数值的计算过程. 直白来讲,就 ...
- [敏捷软工团队博客]Beta阶段测试报告
项目 内容 2020春季计算机学院软件工程(罗杰 任健) 博客园班级博客 作业要求 Beta阶段测试报告 我们在这个课程的目标是 在团队合作中锻炼自己 这个作业在哪个具体方面帮助我们实现目标 对Bet ...