当前位置: 首页 > news >正文

Java 继承(上)

Java 继承 (上)

文章目录

  • Java 继承 (上)
  • 1. 为什么需要继承
  • 2. 继承的概念
  • 3. 继承的语法
  • 4.父类成员在子类中的访问
    • 4.1 子类中访问父类的成员变量
      • 4.1.1 子类和父类不存在同名的成员变量
      • 4.1.2 子类和父类存在同名的成员变量
      • 4.1.3 子类中访问父类的成员变量总结:
    • 4.2 子类中访问父类的成员方法
      • 4.2.1 子类和父类不存在相同的成员方法
      • 4.2.2 子类和父类存在相同的成员方法
      • 4.2.3 子类中访问父类的成员方法总结:
    • 4.3 本知识点的总结:
  • 5. super关键字
    • super 关键字的简单演示
    • super 关键字的用法
    • super 关键字的注意事项
  • 6. 总结:

观前提醒:如果你没学完 Java类和对象 的基础知识,或者没有看过我写的 JAVA 初识类和对象(上)这篇博客,需要你先进去我的主页,认真学习完这篇博客了,再过来看 Java继承(上)


本节目标:

  1. 为什么需要继承
  2. 了解什么是继承(继承的概念)
  3. 如何实现继承(继承的语法)
  4. 父类的成员在子类中的访问
  5. 认识 super关键字 和 了解 super关键字的作用

1. 为什么需要继承

为了更好的引出继承的概念,我们先写几个代码给大家看看:
写一个 Dog 类,写一个 Cat 类,再写一个 Test类,Test类内,创建main方法,用来实例化 Dog 和 Cat类,同时,调用 Dog 和 Cat类的方法。

Dog类:

public class Dog {private String name;private int age;public Dog(String name, int age) {this.name = name;this.age = age;}public void sleep() {System.out.println(this.name+"正在睡觉...");}public void eat() {System.out.println(this.name+"正在吃饭...");}public void bark() {System.out.println(this.name+"正在汪汪叫...");}
}

Cat类:

public class Cat {private String name;private int age;public Cat(String name, int age) {this.name = name;this.age = age;}public void sleep() {System.out.println(this.name+"正在睡觉...");}public void eat() {System.out.println(this.name+"正在吃饭...");}public void mimi() {System.out.println(this.name+"正在咪咪叫...");}
}

Test类:

public class Test {public static void main(String[] args) {Dog dog = new Dog("旺财",10);dog.bark();dog.sleep();dog.eat();Cat cat = new Cat("小虎",6);cat.mimi();cat.sleep();cat.eat();}
}

运行结果:
在这里插入图片描述

根据运行结果,可以知道,Test类内,实例化了 Dog 和 Cat 类,并利用对象的引用,成功调用了 Dog类内的方法,Cat类内的方法。

但是,通过观察可以发现,Dog类和Cat类的代码里面,有着可优化的地方,那就是,这两个类里面,重复的代码太多了!!!
在这里插入图片描述
那么有没有办法,把这些重复的这段代码给提取出来,单独放到一块呢?
有!需要使用到继承的设计思想。

那,什么是继承???
对每个类的共性(重复的代码)进行抽取,这样的设计思想,我们就把他称之为 “继承”!!!

2. 继承的概念

什么叫做"继承"? 继承在现实生活中的意思和代码中的"继承",其实意思是差不多的,我们可以用现实生活中,儿子继承了父亲的财产一样,来理解继承。

继承:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类(也叫做子类)。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用

从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态(后序讲)。
继承是多态实现的基本,没有继承,就没有多态的产生,所以,一定要学好继承,才能够理解并实现多态!!!

注意:继承 或者是后面介绍到的多态并不是只有 Java 才有的设计思想,而是 面向对象的语言,都有的设计思想,例如:C++,Python 这种可以面向对象的语言,均有继承和多态的概念,只不过不同的语言,实现继承和多态的方法略有不同而已。

例如:狗和猫都是动物,那么我们就可以将共性的内容(重复的代码)进行抽取,采用继承的思想来达到代码的共用。
可以用这样一张图来演示一下:
在这里插入图片描述

这样一张图,可以清楚的体现了继承的设计思想,那么,如果Dog类和Cat类想要获取那部分重复的代码来用,该如何获取呢?也就是说,该如何实现继承呢?

3. 继承的语法

在Java当中,如果要实现类与类之间的继承,我们需要使用到 extends 关键字
继承的语法如下:

public class 子类 extends 父类 {
// …
}

为了后续的演示更加方便,以及不让代码变得复杂,我把上面 Dog类 和 Cat类 中的成员变量的访问修饰限定符,由 private 换成 public ,跟着这个博客去敲代码的时候,记得要换一下!

举个例子吧,我们先创建一个 Animal类,作为 父类,里面存放 Dog类 和 Cat类 中重复的代码:

public class Animal {public String name;public int age;public void sleep() {System.out.println(this.name+"正在睡觉...");}public void eat() {System.out.println(this.name+"正在吃饭...");}
}
public class Dog extends Animal{// ...
}

这段代码中:
Dog类 被称为 子类 或者 派生类,为了更好让大家看的懂,下面提及 子类/派生类 的时候,统一称为子类
Animal类 被称为 父类 或者 基类,有些书上,甚至由叫 超类,不过,为了大家更好理解这部分知识,下面提及 父类/基类/超类 的时候,统一称为 父类

这段代码中,我们就说:Dog 这个类 继承了 Animal这个类,Dog这个类,是Animal的子类Animal这个类,是 Dog这个类的父类
听着很绕?没关系,我们可以简单理解为:Animal类 是父亲,Dog类 是儿子,就行。
所以,Dog类 和 Animal类 建立继承关系以后,Animal类当中有什么,Dog类当中就同样有什么

如图所示:
在这里插入图片描述
从这张图可以看出,Dog类内,会继承 Animal类 中所有的成员方法和成员变量,即:Animal类中有什么,Dog类中就有什么,而且还可以有除了 Animal类内 其他的成员变量或者成员方法。

注意:
子类继承父类之后必须要新添加自己特有的成员,体现出与父类的不同,否则这种继承就没有意义了,就如 Dog类 继承 Animal类一样,除了 Animal类中有的,自己还有个 bark() 方法,体现了与 Animal类的不同。

4.父类成员在子类中的访问

为了更好的演示这块内容,我们需要先创建一个包demo2,然后在dome2包里面,创建三个类,第一个类是 Derived类,这个类,当作子类,第二个类是 Base类,作为父类,第三个类是Test类,里面创建main()方法,用来测试代码的。

至于这三个类里面放什么,根据不同的情况去放不同的内容。

4.1 子类中访问父类的成员变量

分为两种情况:

  1. 子类和父类不存在同名的成员变量
  2. 子类和父类存在同名的成员变量

均先展示代码,然后解释。

4.1.1 子类和父类不存在同名的成员变量

public class Base {   // 父类public int a = 10;public int b = 20;
}
///
public class Derived extends Base{ // 子类//子类和父类没有相同成员变量的情况public int c = 30;public void printf() {System.out.println("a = "+this.a);//从父类继承下来的成员变量 aSystem.out.println("b = "+this.b);//从父类继承下来的成员变量 bSystem.out.println("c = "+this.c);//访问子类自己的成员变量 c}
}
///
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.printf();}
}

运行结果:
在这里插入图片描述
可以看到,当子类中没有和父类有同名的成员变量的时候,使用的是继承下来的和自己有的。

4.1.2 子类和父类存在同名的成员变量

public class Base {   // 父类public int a = 10;public int b = 20;
}
///
public class Derived extends Base{ // 子类//子类和父类存在相同成员变量的情况public int c = 30;public int a = 100; // 子类和父类 有相同的成员变量public void printf() {System.out.println("a = "+this.a); // 子类 和 父类 都有这个变量System.out.println("b = "+this.b); // 访问父类中的成员变量 bSystem.out.println("c = "+this.c); // 访问子类自己的成员变量 c}
}
///
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.printf();}
}

运行结果:
在这里插入图片描述
从代码的运行结果可以看出,子类和父类成员变量同名优先使用的是子类的成员变量。

4.1.3 子类中访问父类的成员变量总结:

在子类方法中 或者 通过子类对象访问成员时:

  • 如果访问的成员变量子类中有优先访问自己的成员变量
  • 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类没有定义,则编译报错。
  • 如果访问的成员变量与父类中成员变量同名(相同),则优先访问自己的

成员变量访问遵循就近原则自己有优先自己的,如果没有则向父类中找。

4.2 子类中访问父类的成员方法

首先,在这一块我们讲的是,子类中访问父类的成员方法,同样分为两种情况:

  1. 子类和父类不存在相同的成员方法
  2. 子类和父类存在相同的成员方法

我们这里讲的是相同的成员方法,而不是相同名字的成员方法。有什么区别呢?

首先,我们来介绍什么是相同的方法:

  1. 方法名相同
  2. 形式参数列表相同,包括:形式参数的数据类型,个数,顺序,这三个条件,都要同时满足。
  3. 返回值不做要求。

所以,如果仅仅只是方法名字相同,并不能满足方法相同,而 4.2.2标题 的内容,需要的是相同的成员方法,才能显示出我们想要的结果。

4.2.1 子类和父类不存在相同的成员方法

public class Base {public void func_A() {System.out.println("这是父类中的func_A方法");}
}
//
public class Derived extends Base {// 子类 和 父类 没有相同成员方法 的情况public void func_B() {System.out.println("这是子类的func_B方法");}public void print_method() {func_A(); // 访问从父类继承下来的方法func_B(); // 访问子类自己的方法}
}
/
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.print_method();}
}

运行结果:
在这里插入图片描述

可以看到,当子类中没有和父类中相同的成员方法的时候,使用的是继承下来的和自己有的。

4.2.2 子类和父类存在相同的成员方法

public class Base {public void func_A() {System.out.println("这是父类中的func_A方法");}
}
/
public class Derived extends Base {// 存在 相同成员方法的情况public void func_A() {System.out.println("这是子类中的func_A方法.....");}public void func_B() {System.out.println("这是子类的func_B方法");}public void print_method() {func_A(); // 父类 和 子类 都有这个方法func_B(); // 访问子类自己的方法}
}

public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.print_method();}
}

运行结果:
在这里插入图片描述
从代码的运行结果可以看出,子类中父类当中相同的成员方法时,优先使用的是子类的成员方法

注意!必须是满足方法相同的情况下,只有方法名相同的情况下是不行的。

看下面这张图所演示的,只满足方法同名的情况下:
在这里插入图片描述
所以,只有方法名相同的情况下,是不能达到子类和父类中同时有相同的方法优先使用子类的效果的。

4.2.3 子类中访问父类的成员方法总结:

  • 在子类对象中访问父类不相同的成员方法的时候,优先在子类当中去寻找,如果子类当中没有,则去父类当中找父类找不到的话,就编译报错
  • 在子类对象中访问父类相同的成员方法的时候,优先使用子类的。

4.3 本知识点的总结:

当子类和父类有相同的成员方法或成员变量的时候,优先访问子类的
遵循就近原则自己有优先使用自己的,如果没有则向父类中找

但是,如果在具有相同的成员方法或成员变量的情况下,要在子类方法中访问父类中相同的成员方法或成员变量时,那该怎么办?
答:使用 super 关键字

5. super关键字

由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员

super 关键字的简单演示

接下来,还是看一段代码,代码里面父类和子类有相同的 变量a ,使用 super 关键字在子类中访问 变量a:

public class Base {public int a = 10;
}
//
public class Derived extends Base {int a = 100;public void printf() {System.out.println("同名情况下,访问子类的" + " a = " + this.a);System.out.println("使用 super 关键字,访问父类的" + " a = " + super.a);}
}
//
public class Test {public static void main(String[] args) {Derived derived = new Derived();derived.printf();}
}

运行结果:

在这里插入图片描述
以 变量 a 为例子,简单使用了一下 super 关键字,

所以,在子类中,如果想要明确访问父类的成员时,借助super关键字即可。

super 关键字的用法

super 关键字 和 this 关键字一样,有三种用法:

  1. 可以通过 super 访问 当前对象的父类的 成员变量,如:super.变量名
  2. 可以通过 super 访问 当前对象的父类的 成员方法,如:super.方法名( )
  3. 可以通过 super 访问 当前对象的父类的 构造方法,如:super( )

第三点用法,在 Java 继承(下) 这篇博客的第一个标题内容【子类的构造方法】中,详细介绍。

super 关键字的注意事项

【注意事项】

  1. 只能在非静态方法中使用
  2. 在子类方法中,访问父类的成员变量和方法。
  3. super 只能指代当前类的父类,不能指代父类的父类,如:super.super.a,这样是错误的!

6. 总结:

由于 Java 继承这部分可讲的东西挺多的,为了避免这篇博客太长了,我将 java 继承部分拆分成 上,下两篇博客。

看到这篇博客的读者,如果需要,可以点击我的头像,进入主页,查看 Java 继承(下)这篇博客,看完这两篇博客,相信你会对Java 继承方面的知识有一个全面的了解,至于需要更深入的了解,则需要你多多练习代码了!

希望这篇文章,可以帮助你对 Java 继承有一个初步的了解,为后面的 java 多态做准备,如果这篇文章内容有错误的,欢迎指出!

相关文章:

  • JavaScript性能优化全景指南
  • STM32的DMA入门指南:让单片机学会“自动搬运“数据
  • 自动驾驶决策规划框架详解:从理论到实践
  • Asp.Net Core 通过JWT版本号实现JWT无法提前撤回的问题
  • GitHub push失败解决办法-fatal: unable to access ‘https://github.com/xxx
  • 封装文档核心知识点总结(通俗版)
  • 局域协作中的前端调试:WebDebugX 在本地多端调试中的实践
  • 自动驾驶中的博弈式交互规划:从理论到实践
  • @vue/composition-api
  • LINUX安装运行jeelowcode后端项目(idea启动)
  • kerberos在无痕浏览器 获取用户信息失败 如何判断是否无痕浏览器
  • 设计模式-开放封闭原则
  • AI智能体策略FunctionCalling和ReAct有什么区别?
  • Qtc++开发遇到的问题-按钮点击不管用?
  • 大模型三大缺陷与RAG破解之道
  • 【leetcode】977. 有序数组的平方
  • ComfyUI 文生图,绘图要求中 正向提示词、负向提示词 有什么区别,webp又是什么格式 comfyui 那么喜欢它
  • 导出rpm包的方法
  • 【监控】Prometheus中的告警机制介绍
  • 与 PyCharm 官方沟通解决开发环境问题记录(进展:官方已推出2个新的修复版本)
  • 成都建立网站的公司网站/百度电话查询
  • 家教网站如何做/杭州网站优化企业
  • 做黑彩网站/今日国内新闻最新消息10条新闻
  • 西宁网站建设/百度客服人工在线咨询
  • 怎么制作微信小程序商城/北京seo优化wyhseo
  • 解决方案网站/广东疫情最新资讯