• 给你捋清楚Java面向对象的继承关系


    4.1 继承

    面向对象程序设计语言有三大特性:封装、继承和多态性。继承是面向对象语言的重要特征之一,没有继承的语言只能被称作“使用对象的语言”。继承是非常简单而强大的设计思想,它提供了我们代码重用和程序组织的有力工具。

    类是规则,用来制造对象的规则。我们不断地定义类,用定义的类制造一些对象。类定义了对象的属性和行为,就像图纸决定了房子要盖成什么样子。

    一张图纸可以盖很多房子,它们都是相同的房子,但是坐落在不同的地方,会有不同的人住在里面。假如现在我们想盖一座新房子,和以前盖的房子很相似,但是稍微有点不同。任何一个建筑师都会拿以前盖的房子的图纸来,稍加修改,成为一张新图纸,然后盖这座新房子。所以一旦我们有了一张设计良好的图纸,我们就可以基于这张图纸设计出很多相似但不完全相同的房子的图纸来。

    基于已有的设计创造新的设计,就是面向对象程序设计中的继承。在继承中,新的类不是凭空产生的,而是基于一个已经存在的类而定义出来的。通过继承,新的类自动获得了基础类中所有的成员,包括成员变量和方法,包括各种访问属性的成员,无论是public还是private。当然,在这之后,程序员还可以加入自己的新的成员,包括变量和方法。显然,通过继承来定义新的类,远比从头开始写一个新的类要简单快捷和方便。继承是支持代码重用的重要手段之一。

    类这个词有分类的意思,具有相似特性的东西可以归为一类。比如所有的鸟都有一些共同的特性:有翅膀、下蛋等等。鸟的一个子类,比如鸡,具有鸟的所有的特性,同时又有它自己的特性,比如飞不太高等等;而另外一种鸟类,比如鸵鸟,同样也具有鸟类的全部特性,但是又有它自己的明显不同于鸡的特性。

    如果我们用程序设计的语言来描述这个鸡和鸵鸟的关系问题,首先有一个类叫做“鸟”,它具有一些成员变量和方法,从而阐述了鸟所应该具有的特征和行为。然后一个“鸡”类可以从这个“鸟”类派生出来,它同样也具有“鸟”类所有的成员变量和方法,然后再加上自己特有的成员变量和方法。无论是从“鸟”那里继承来的变量和方法,还是它自己加上的,都是它的变量和方法。

    本周的学习,建议按照视频中的操作,自己把媒体资料库从头到尾实现一遍,重点在于弄清楚子类和父类的关系,理解子类从父类继承得到了什么。

    4.1.1 媒体资料库的设计

    CD.java

    1. class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package onclass;
    2. public class CD extends Item{
    3. // private String title;
    4. private String artist;
    5. private int num_of_tracks;
    6. // private int playing_time;
    7. // private boolean got_it = false;
    8. // private String comment;
    9. public CD(String title, String artist, int num_of_tracks, int playing_time, String comment) {
    10. // super();
    11. super( title, playing_time, false, comment);
    12. // this.title = title;
    13. this.artist = artist;
    14. this.num_of_tracks = num_of_tracks;
    15. // this.playing_time = playing_time;
    16. // this.comment = comment;
    17. }
    18. public static void main(String[] args) {
    19. // TODO Auto-generated method stub
    20. CD cd = new CD( "a", "b", 2, 2, "...");
    21. cd.print();
    22. }
    23. public void print() {
    24. // TODO Auto-generated method stub
    25. System.out.print( "CD:" );
    26. super.print();
    27. System.out.println( ":" + artist);
    28. }
    29. }
  • 4.1.2 继承

    • 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
    • 继承就是 子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
    • 我们把用来做基础派生其它类的那个类叫做父类、超类或者基类,而派生出来的新类叫做子类。Java用关键字extends表示这种继承/派生关系:
    1. class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">class ThisClass extends SuperClass { 
    2. //…
    3. }

CD 与 DVD基本一致,存在着大量的 代码复制 。 除了CD之外,我们还需要DVD,MP3等,他们都很相似,但是重复写对于我们之后维护会很复杂。 所以我们写一个 Item 公共类:

  1. class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package onclass;
  2. public class Item {
  3. private String title;
  4. private int playing_time;
  5. private boolean got_it = false;
  6. private String comment;
  7. public Item() {
  8. }
  9. public Item(String title, int playing_time, boolean got_it, String comment) {
  10. super();
  11. this.title = title;
  12. this.playing_time = playing_time;
  13. this.got_it = got_it;
  14. this.comment = comment;
  15. }
  16. public void print() {
  17. System.out.print(title);
  18. }
  19. }

现在他们几个类编程如下关系,database不再直接和CD、DVD联系。

继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。

extends 关键字

java-面向对象的英雄类
zip 0星 超过10%的资源 7KB
下载
  1. class="hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">class 父类 {
  2. }
  3. class 子类 extends 父类 {
  4. }

implements 关键字

  1. class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">public interface A {
  2. public void eat();
  3. public void sleep();
  4. }
  5. public interface B {
  6. public void show();
  7. }
  8. public class C implements A,B {
  9. }

继承类型

==需要注意的是 Java 不支持多继承,但支持多重继承。==

继承的特性

  1. 子类拥有父类非 private 的属性、方法。
  2. 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  3. 子类可以用自己的方式实现父类的方法。
  4. Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  5. 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

4.2 子类父类关系

对理解继承来说,最重要的事情是,知道哪些东西被继承了,或者说,子类从父类那里得到了什么。答案是:所有的东西,所有的父类的成员,包括变量和方法,都成为了子类的成员,除了构造方法。构造方法是父类所独有的,因为它们的名字就是类的名字,所以父类的构造方法在子类中不存在。除此之外,子类继承得到了父类所有的成员。

java员工类
zip 0星 超过10%的资源 4KB
下载

但是得到不等于可以随便使用。每个成员有不同的访问属性,子类继承得到了父类所有的成员,但是不同的访问属性使得子类在使用这些成员时有所不同:有些父类的成员直接成为子类的对外的界面,有些则被深深地隐藏起来,即使子类自己也不能直接访问。下表列出了不同访问属性的父类成员在子类中的访问属性:

父类成员访问属性在父类中的含义在子类中的含义
public对所有人开放对所有人开放
protected只有包内其它类、自己和子类可以访问只有包内其它类、自己和子类可以访问
缺省只有包内其它类可以访问如果子类与父类在同一个包内:只有包内其它类可以访问,否则:相当于private,不能访问
private只有自己可以访问不能访问

public的成员直接成为子类的public的成员,protected的成员也直接成为子类的protected的成员。Java的protected的意思是包内和子类可访问,所以它比缺省的访问属性要宽一些。而对于父类的缺省的未定义访问属性的成员来说,他们是在父类所在的包内可见,如果子类不属于父类的包,那么在子类里面,这些缺省属性的成员和private的成员是一样的:不可见。父类的private的成员在子类里仍然是存在的,只是子类中不能直接访问。我们不可以在子类中重新定义继承得到的成员的访问属性。如果我们试图重新定义一个在父类中已经存在的成员变量,那么我们是在定义一个与父类的成员变量完全无关的变量,在子类中我们可以访问这个定义在子类中的变量,在父类的方法中访问父类的那个。尽管它们同名但是互不影响。

在构造一个子类的对象时,父类的构造方法也是会被调用的,而且父类的构造方法在子类的构造方法之前被调用。在程序运行过程中,子类对象的一部分空间存放的是父类对象。因为子类从父类得到继承,在子类对象初始化过程中可能会使用到父类的成员。所以父类的空间正是要先被初始化的,然后子类的空间才得到初始化。在这个过程中,如果父类的构造方法需要参数,如何传递参数就很重要了。

super 关键字

  1. class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">class Animal {
  2. void eat() {
  3. System.out.println("animal : eat");
  4. }
  5. }
  6. class Dog extends Animal {
  7. void eat() {
  8. System.out.println("dog : eat");
  9. }
  10. void eatTest() {
  11. this.eat(); // this 调用自己的方法
  12. super.eat(); // super 调用父类方法
  13. }
  14. }
  15. public class Test {
  16. public static void main(String[] args) {
  17. Animal a = new Animal();
  18. a.eat();
  19. Dog d = new Dog();
  20. d.eatTest();
  21. }
  22. }

输出结果:

  1. <pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">animal : eat
  2. dog : eat
  3. animal : eat
  4. pre>
  1. class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">public class Item {
  2. private String title;
  3. public Item() {
  4. }
  5. public Item(String title, int playing_time, boolean got_it, String comment) {
  6. super();
  7. this.title = title;
  8. this.playing_time = playing_time;
  9. this.got_it = got_it;
  10. this.comment = comment;
  11. }
  12. public void print() {
  13. System.out.print(title);
  14. }
  15. }
  16. public class CD extends Item{
  17. public CD(String title, String artist, int num_of_tracks, int playing_time, String comment) {
  18. // super();
  19. super( title, playing_time, false, comment);
  20. // this.title = title;
  21. this.artist = artist;
  22. this.num_of_tracks = num_of_tracks;
  23. }
  24. }
  • 相关阅读:
    Verilog实现定点乘法器
    UG NX二次开发(C#)-创建点到曲线(边)的切线
    element组件踩坑记录
    multisim仿真电路图红绿灯
    ubuntu docker 部署 vue 项目
    DCS系统组态设计实验
    【设计模式实践笔记】第三节:建造者模式
    2023年起重信号司索工(建筑特殊工种)证考试题库及起重信号司索工(建筑特殊工种)试题解析
    员工脉动调查中十个最佳问题
    《HelloGitHub》第 95 期
  • 原文地址:https://blog.csdn.net/weixin_62421895/article/details/126059424