Java 复用类-继承-笔记

继承的语法

介绍

创建一个类时肯定会进行继承,因为若非如此,会从 Java 的标准根类 Object 中继承。

继承采用了一种与“合成”全然不同的形式。需要继承的时候,我们会说:“这个新类和那个旧类差不多。” 为了在代码里表达这一观念, 需要给出类名。但在类主体的花括号之前,需要放置一个关键字extends,在后面跟随“基础类”的名字。若采取这种做法,就可自动获得基础类的所有数据成员及方法。

摘录于《Java编程思想(第四版)》

刚开始学习Java,我对类的意义不太理解,我感觉除了在多人协作时更加方便以外不知道还有什么用处。

在继承了基础类之后,基础类的方法都可以在新类中直接使用,感觉就是把基础类的代码复制一遍放在新类的代码中?

书中的示例代码:

//: Detergent.java
// Inheritance syntax & properties

class Cleanser {
    private String s = new String("Cleanser");
    public void append(String a) { s += a; }
    public void dilute() { append(" dilute()"); }
    public void apply() { append(" apply()"); }
    public void scrub() { append(" scrub"); }
    public void print() { System.out.println(s); }
    public static void main(String[] args) {
        Cleanser x = new Cleanser();
        x.dilute(); x.apply(); x.scrub();
        x.print();
    }
}

public class Detergent extends Cleanser{
    // Change method:
    public void scrub() {
        append(" Detergent.scrub()");
        super.scrub(); // Call base-class version
    }
    // Add method to the interface:
    public void foam() { append(" foam()"); }
    //Test the new class:
    public static void main(String[] args){
        Detergent x = new Detergent();
        x.dilute();
        x.apply();
        x.scrub();
        x.foam();
        x.print();
        System.out.println("Testing base class:");
        Cleanser.main(args);
    }
}
output:
Cleanser dilute() apply() Detergent.scrub() scrub foam()
Testing base class:
Cleanser dilute() apply() scrub

知识点

  1. 可以为每个类都创建一个main()方法。这种在每个类中都设置一个main()方法的技术可使每个类的单元测试都变得简单易行。而且在完成单元测试之后,也无需删除main(),可以将其留待下次测试
  2. 继承会同时继承 public static void main方法,调用的方法是 Cleanser.main(args);
  3. 基础类中所有的方法都必须是public的。为了继承,一般的规则是将所有的数据成员都指定为private,将所有的方法指定为public(特殊情况也可以做出调整)。
  4. 如果有相同名称的方法,直接用就是使用新类中的方法。使用基础类的方法是:super.scrub();
  5. java用super关键字表示超类的意思,当前类就是从超类继承来的。为此,表达式super.scrub()将调用基类版本的scrub()方法
  6. 如果新类中没有添加相同名称的方法,可以直接调用基础类中的方法
  7. 在继承的过程中,并不一定非得使用基类的方法。也可以在导出类中添加新方法,。其添加方式与在类中添加任意方法一样,即对其加以定义即可。

疑惑

  • 接触Java后对Java程序的架构不太理解,一个project 中的src 中可以建立很多java 类,每个java 类中都可以有public static void main(String[] args),那么这些.java之间的关联是什么?
  • ctrl+shift+F10是运行选中的类中的main方法,看起来并不是运行整个项目?
  • 如果只能有一个public static main的话我还能理解,这么多类都有main,那么到底哪个才是程序的开始?他们是一个项目中的吗?
  • 在一个src中创建多个有main的java类的原因是我在学习的时候直接把所有学到的类放在一起了,一开始发现可以单独运行,没啥关系。看到一个.java中也可以有两个main,我就更疑惑了,所以先把这个写出来,以后看看能不能回来填坑

初始化基类

默认构造器

从外部来看,导出类就像一个与基类具有相同接口的新类,或许还会有一些额外的方法和域。但继承并不只是复制基类的接口。当创建了一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象时一样的。二者的区别在于,后者来自于外部,而基类的子对象被包装在导出类的对象内部。

java用来保证基类子对象正确初始化的方法:在构造器中调用基类构造器来执行初始化,而基类构造器具有执行基类初始化所需要的所有知识和能力。Java会自动在导出类的构造器中插入对基类构造器的调用。

摘录于《Java编程思想(第四版)》

书中的示例:

//: reusing/Cartoon.java
// Constructor calls during inheritance.
import static net.mindview.util.Print.*;

class Art {
    Art() {print("Art constructor"); }
}

class Drawing extends Art {
    Drawing() { print("Drawing constructor"); }
}

public class Cartoon extends Drawing {
    public Cartoon() { print("Cartoon constructor"); }
    public static void main(String[] args) {
        Cartoon x = new Cartoon();
    }
}
output:
Art constructor
Drawing constructor
Cartoon constructor

可以看到,Cartoon是Drawing的导出类,Drawing是Art的导出类。他们都各自自定义了构造器,并且在代码上没有包含基类的构造器。也就是说,Java是自动并且强制帮你加上基类的构造器的,不需要我们手动添加。

Cartoon x = new Cartoon(); 其实可以理解为在创建一个Cartoon对象的时候自动创建了一个Drawing子对象和Art子对象,这样的理解更切合正常思维。就是不知道这两个子对象能不能单独拿出来使用了

另外,在新建对象的时候对象的初始化是从最基础的类开始初始化的,也就是先初始化Art子对象,再是Drawing子对象,最后是Cartoon对象。(不过似乎也不能这么说,应该说先执行Art类的构造器,在执行Drawing的构造器,最后是Cartoon的)

带参数的构造器

上例中个各类均含有默认的构造器。即这些构造器都不带参数。编译器可以轻松地调用它们是因为不必考虑要传递什么样的参数的问题。但是, 如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显示地编写调用基类构造器的语句,并且配以适当的参数列表。

摘录于《Java编程思想(第四版)》

书中的示例:

//: reusing/Chess.java
// Inheritance. constructors and arguments.
import static net.mindview.util.Print.print;

class Game {
    Game(int i) {
        print("Game constructor");
    }
}

class BoardGame extends Game {
    BoardGame(int i) {
        super(i);
        print("BoardGame constructor");
    }
}

public class Chess extends BoardGame {
    Chess() {
        super(11);
        print("Chess constructor");
    }
    public static void main(String[] args) {
        Chess x = new Chess();
    }
}
output:
Game constructor
BoardGame constructor
Chess constructor

这个还是比较好理解的,如果你想往下传递参数,就要用到超类关键词:super(xxx);

所有的参数应该都可以这样传,算是一个小而有用的知识点

说点什么

avatar

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  Subscribe  
提醒