第三知识单元

面向对象程序设计

Java程序设计 第6讲,主讲人:李欣

Created: 2024-10-16 Wed 16:35

0.1. 互动课堂

Click to host the seminar.

0.2. 签到

https://dash.memopixel.com/tool/attendance/

0.3. 本次课的目标

  • 理解多态的含义
  • 理解方法的重载
  • 理解构造函数的重载
  • 包结构与使用
  • 接口与接口实现

1. 方法覆盖实现的多态

public class Main {
    public static void main(String[] args) {
        Chinese c = new Chinese();
        c.setName("张三");
        c.setPinyin("Zhang San");
        c.sayHello();
        British b = new British();
        b.setName("Henry");
        b.sayHello();
        Japanese j = new Japanese();
        j.setName("田中一郎");
        j.setFurigana("たなかいちろう");
        j.sayHello();
        Korean k = new Korean();
        k.setName("한모나이");
        k.sayHello();
    }
}
class Person {
    private String name;
    private String gender;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void sayHello() {
        System.out.println("Hello.");
    }
}
class Chinese extends Person {
    private String pinyin;
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
}
class British extends Person {
    public void sayHello() {
        System.out.println("Hello, I'm " + getName() + ". Nice to meet you!");
    }
}
class Japanese extends Person {
    private String furigana;
    public String getFurigana() {
        return furigana;
    }
    public void setFurigana(String furigana) {
        this.furigana = furigana;
    }
    public void sayHello() {
        System.out.println("こんにちは、" + getName() + (furigana == null ? "" : "(" + furigana + ")") + "です。よろしくお願いします。");
    }
}
class Korean extends Person {
    public void sayHello() {
        System.out.println("안녕하세요 " + getName() + "입니다. 만나서 반가워요.");
    }
}
你好,我是张三(Zhang San)。很高兴认识你!
Hello, I'm Henry. Nice to meet you!
こんにちは、田中一郎(たなかいちろう)です。よろしくお願いします。
안녕하세요 한모나이입니다. 만나서 반가워요.

2. 方法重载实现的多态

public class Main {
    public static void main(String[] args) {
        Chinese c = new Chinese();
        c.setName("张三");
        c.setPinyin("Zhang San");
        c.sayHello();
        c.sayHello("李四");
        c.sayHello("李四", "王五");
    }
}
class Chinese extends Person {
    private String pinyin;
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String guestName) {
        System.out.println("你好" + guestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String firstGuestName, String secondGuestName) {
        System.out.println("你好" + firstGuestName + "、" + secondGuestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你们!");
    }
}
你好,我是张三(Zhang San)。很高兴认识你!
你好李四,我是张三(Zhang San)。很高兴认识你!
你好李四、王五,我是张三(Zhang San)。很高兴认识你们!

3. 对象引用的多态

对象的 引用型 变量 具有 多态性 ,因为一个 引用型 变量 可以指向不同形式的对象, 这主要是基于一个事实:

子类 对象可以作为 父类 对象来使用。

public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Chinese("张三");
        p[1] = new British("Henry");
        p[2] = new Japanese("山下次郎");
        p[3] = new Korean("한모나이");
        for (int i = 0; i < 4; i++) {
            p[i].sayHello();
        }
    }
}
class Person {
    private String name;
    private String gender;
    private int age;
    Person(String name) {
        setName(name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void sayHello() {
        System.out.println("Hello.");
    }
}
class Chinese extends Person {
    private String pinyin;
    Chinese(String name) {
        super(name);
    }
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String guestName) {
        System.out.println("你好" + guestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String firstGuestName, String secondGuestName) {
        System.out.println("你好" + firstGuestName + "、" + secondGuestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你们!");
    }
}
class British extends Person {
    British(String name) {
        super(name);
    }
    public void sayHello() {
        System.out.println("Hello, I'm " + getName() + ". Nice to meet you!");
    }
}
class Japanese extends Person {
    private String furigana;
    Japanese(String name) {
        super(name);
    }
    public String getFurigana() {
        return furigana;
    }
    public void setFurigana(String furigana) {
        this.furigana = furigana;
    }
    public void sayHello() {
        System.out.println("こんにちは、" + getName() + (furigana == null ? "" : "(" + furigana + ")") + "です。よろしくお願いします。");
    }
}
class Korean extends Person {
    Korean(String name) {
        super(name);
    }
    public void sayHello() {
        System.out.println("안녕하세요 " + getName() + "입니다. 만나서 반가워요.");
    }
}
你好,我是张三。很高兴认识你!
Hello, I'm Henry. Nice to meet you!
こんにちは、山下次郎です。よろしくお願いします。
안녕하세요 한모나이입니다. 만나서 반가워요.
public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Chinese("张三");
        p[1] = new British("Henry");
        p[2] = new Japanese("山下次郎");
        p[3] = new Korean("한모나이");
        for (int i = 0; i < 4; i++) {
            p[i].sayHello();
        }
        Chinese c = new Person("张三");
    }
}
javac Main.java
javac Main.java
# Main.java:11: error: incompatible types: Person cannot be converted to Chinese
#         Chinese c = new Person("张三");
#                           ^
# 1 error
public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Chinese("张三");
        p[0].setPinyin("Zhang San");
        p[1] = new British("Henry");
        p[2] = new Japanese("山下次郎");
        p[3] = new Korean("한모나이");
        for (int i = 0; i < 4; i++) {
            p[i].sayHello();
        }
    }
}
javac Main.java
javac Main.java
# Main.java:5: error: cannot find symbol
#         p[0].setPinyin("Zhang San");
#             ^
#   symbol:   method setPinyin(String)
#   location: class Person
# 1 error
public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Chinese("张三");
        ((Chinese)p[0]).setPinyin("Zhang San");
        p[1] = new British("Henry");
        p[2] = new Japanese("山下次郎");
        p[3] = new Korean("한모나이");
        for (int i = 0; i < 4; i++) {
            p[i].sayHello();
        }
    }
}
你好,我是张三(Zhang San)。很高兴认识你!
Hello, I'm Henry. Nice to meet you!
こんにちは、山下次郎です。よろしくお願いします。
안녕하세요 한모나이입니다. 만나서 반가워요.
public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Chinese("张三");
        ((Chinese)p[0]).setPinyin("Zhang San");
        p[1] = new British("Henry");
        p[2] = new Japanese("山下次郎");
        p[3] = new Korean("한모나이");
        for (int i = 0; i < 4; i++) {
            p[i].sayHello();
        }
        Person person = new Person("张三");
        Chinese c = (Chinese) person;
    }
}
javac Main.java
javac Main.java
java Main
javac Main.java
java Main
# 你好,我是张三(Zhang San)。很高兴认识你!
# Hello, I'm Henry. Nice to meet you!
# こんにちは、山下次郎です。よろしくお願いします。
# 안녕하세요 한모나이입니다. 만나서 반가워요.
# Exception in thread "main" java.lang.ClassCastException: class Person cannot be cast to class Chinese (Person and Chinese are in unnamed module of loader 'app')
#       at Main.main(Main.java:13)
public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Chinese("张三");
        p[1] = new British("Henry");
        p[2] = new Japanese("山下次郎");
        p[3] = new Korean("한모나이");
        for (int i = 0; i < 4; i++) {
            System.out.print((p[i] instanceof Person) + " " +
                             (p[i] instanceof Chinese) + " " +
                             (p[i] instanceof British) + " " +
                             (p[i] instanceof Japanese) + " " +
                             (p[i] instanceof Korean) + " ");
            p[i].sayHello();
        }
    }
}
true true false false false 你好,我是张三。很高兴认识你!
true false true false false Hello, I'm Henry. Nice to meet you!
true false false true false こんにちは、山下次郎です。よろしくお願いします。
true false false false true 안녕하세요 한모나이입니다. 만나서 반가워요.

4. 构造函数的重载

4.1. 构造函数的重载

构造函数重载 是指 同一个类 中存在着 若干个 具有 不同参数列表构造函数

当一个类定义了 若干个构造函数 时,创建该类对象的语句会 自动 根据给出的 实际参数数目类型顺序 来确定调用 哪个构造函数 来完成对新对象的 初始化工作

public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Person();
        p[1] = new Person("张三");
        p[2] = new Person("张三", "男");
        p[3] = new Person("张三", "男", 28);
        for (int i = 0; i < 4; i++) {
            System.out.println("Name: " + p[i].getName() +
                               " Gender: " + p[i].getGender() +
                               " Age: " + p[i].getAge());
        }
    }
}
class Person {
    private String name;
    private String gender;
    private int age;
    Person () {}
    Person(String name) {
        setName(name);
    }
    Person(String name, String gender) {
        this(name);
        setGender(gender);
    }
    Person(String name, String gender, int age) {
        this(name, gender);
        setAge(age);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void sayHello() {
        System.out.println("Hello.");
    }
}
Name: null Gender: null Age: 0
Name: 张三 Gender: null Age: 0
Name: 张三 Gender: 男 Age: 0
Name: 张三 Gender: 男 Age: 28

4.2. 调用父类的构造函数

4.2.1. 子类没有定义构造函数的情况

public class Main {
    public static void main(String[] args) {
        Chinese c = new Chinese();
    }
}
class Person {
    private String name;
    private String gender;
    private int age;
    Person () {
        System.out.println("Constructor Person() from Person class.");
    }
    Person(String name) {
        setName(name);
    }
    Person(String name, String gender) {
        this(name);
        setGender(gender);
    }
    Person(String name, String gender, int age) {
        this(name, gender);
        setAge(age);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void sayHello() {
        System.out.println("Hello.");
    }
}
class Chinese extends Person {
    private String pinyin;
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String guestName) {
        System.out.println("你好" + guestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String firstGuestName, String secondGuestName) {
        System.out.println("你好" + firstGuestName + "、" + secondGuestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你们!");
    }
}
Constructor Person() from Person class.

4.2.2. 子类定义了构造函数的情况

public class Main {
    public static void main(String[] args) {
        Chinese c = new Chinese("张三");
        System.out.println(c.getName());
    }
}
class Chinese extends Person {
    private String pinyin;
    Chinese(String name) {
        setName(name);
    }
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String guestName) {
        System.out.println("你好" + guestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String firstGuestName, String secondGuestName) {
        System.out.println("你好" + firstGuestName + "、" + secondGuestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你们!");
    }
}
Constructor Person() from Person class.
张三

4.2.3. 子类定义的构造函数中使用 super 调用父类构造函数的情况

public class Main {
    public static void main(String[] args) {
        Chinese c = new Chinese("张三");
        System.out.println(c.getName());
    }
}
class Chinese extends Person {
    private String pinyin;
    Chinese(String name) {
        super(name);
    }
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String guestName) {
        System.out.println("你好" + guestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String firstGuestName, String secondGuestName) {
        System.out.println("你好" + firstGuestName + "、" + secondGuestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你们!");
    }
}
张三

4.2.4. 构造函数重载及调用父类构造函数综合应用

public class Main {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        p[0] = new Chinese("张三", "男", 25, "Zhang San");
        p[1] = new Chinese("李四");
        p[2] = new Chinese("小红", "女", 18);
        p[3] = new British("Henry");
        for (int i = 0; i < 4; i++) {
            System.out.print(p[i].getName() + " " + p[i].getGender() + " " + p[i].getAge() + " " +
                             ((p[i] instanceof Chinese) ? ((Chinese)p[i]).getPinyin() : "") + " : ");
            p[i].sayHello();
        }
    }
}
class Chinese extends Person {
    private String pinyin;
    Chinese(String name) {
        super(name);
    }
    Chinese(String name, String gender) {
        super(name, gender);
    }
    Chinese(String name, String gender, int age) {
        super(name, gender, age);
    }
    Chinese(String name, String gender, int age, String pinyin) {
        super(name, gender, age);
        setPinyin(pinyin);
    }
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String guestName) {
        System.out.println("你好" + guestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String firstGuestName, String secondGuestName) {
        System.out.println("你好" + firstGuestName + "、" + secondGuestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你们!");
    }
}
张三 男 25 Zhang San : 你好,我是张三(Zhang San)。很高兴认识你!
李四 null 0 null : 你好,我是李四。很高兴认识你!
小红 女 18 null : 你好,我是小红。很高兴认识你!
Henry null 0  : Hello, I'm Henry. Nice to meet you!

4.3. 对象初始化的过程

参考教材

  • 5.5.3 pp.131-133

4.3.1. 为对象分配内存空间后的属性单元初始化

class Main {
    public static void main(String[] args) {
        int i;
        boolean b;
        String s;
        System.out.println("i: " + i + ", b: " + b + ", s: " + s);
    }
}
javac Main.java
# Main.java:6: error: variable i might not have been initialized
#         System.out.println("i: " + i + ", b: " + b + ", s: " + s);
#                                    ^
# Main.java:6: error: variable b might not have been initialized
#         System.out.println("i: " + i + ", b: " + b + ", s: " + s);
#                                                  ^
# Main.java:6: error: variable s might not have been initialized
#         System.out.println("i: " + i + ", b: " + b + ", s: " + s);
#                                                                ^
# 3 errors
class Main {
    public static void main(String[] args) {
        Test test = new Test();
        System.out.println("i: " + test.i + ", b: " + test.b + ", s: " + test.s);
    }
}
class Test {
    int i;
    boolean b;
    String s;
}
i: 0, b: false, s: null
class Main {
    public static void main(String[] args) {
        Test test;
        System.out.println("test: " + test);
    }
}
class Test {
    int i;
    boolean b;
    String s;
}
javac Main.java
# Main.java:4: error: variable test might not have been initialized
#         System.out.println("test: " + test);
#                                       ^
# 1 error
class Main {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("t.test: " + t.test);
    }
}
class Test {
    int i;
    boolean b;
    String s;
    Test test;
}
t.test: null
class Main {
    static int i;
    static boolean b;
    static String s;
    public static void main(String[] args) {
        System.out.println("i: " + i + ", b: " + b + ", s: " + s);
    }
}
i: 0, b: false, s: null

4.3.2. 执行显式初始化

class Main {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("i: " + t.i + ", b: " + t.b + ", s: " + t.s);
    }
}
class Test {
    int i;
    boolean b = true;
    String s;
}
i: 0, b: true, s: null

4.3.3. 执行构造方法中的初始化

class Main {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("i: " + t.i + ", b: " + t.b + ", s: " + t.s);
    }
}
class Test {
    int i;
    boolean b;
    String s;
    Test() {
        i = 100;
        b = true;
        s = "test";
    }
}
i: 100, b: true, s: test
public class Main {
    public static void main(String[] args) {
        Person p = new Chinese("张三");
        System.out.println(p.getName() + ", " +
                           p.getGender() + ", " +
                           p.getAge() + ", " +
                           ((Chinese)p).getPinyin());
    }
}
class Chinese extends Person {
    private String pinyin;
    Chinese(String name) {
        super(name, "性别未填写");
        pinyin = "姓名拼音未填写";
    }
    Chinese(String name, String gender) {
        super(name, gender);
    }
    Chinese(String name, String gender, int age) {
        super(name, gender, age);
    }
    Chinese(String name, String gender, int age, String pinyin) {
        super(name, gender, age);
        setPinyin(pinyin);
    }
    public String getPinyin() {
        return pinyin;
    }
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }
    public void sayHello() {
        System.out.println("你好,我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String guestName) {
        System.out.println("你好" + guestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你!");
    }
    public void sayHello(String firstGuestName, String secondGuestName) {
        System.out.println("你好" + firstGuestName + "、" + secondGuestName + ",我是" + getName() + (pinyin == null ? "" : "(" + pinyin + ")") + "。很高兴认识你们!");
    }
}
张三, 性别未填写, 0, 姓名拼音未填写

5. 包及其使用

参考教材

  • 5.6 pp.133-138

6. 接口

参考教材

  • 5.7 pp.138-142