学习java的第三周

面对对象编程(二)

继承

class Person {
    private String name;
    private int age;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
}

class Student extends Person {
    // 不要重复name和age字段/方法,
    // 只需要定义新增score字段/方法:
    private int score;

    public int getScore() { … }
    public void setScore(int score) { … }
}

Student(子类),Person(父类)

  • 利用extends关键字来实现继承,可以不用再Student中写Person相同的部分。
  • 但是上述代码有个问题,子类无法访问父类的private字段或者private方法,但是可以把private改为protected,用protected修饰的字段可以被子类访问。

关键字super

class Student extends Person {
    public String hello() {
        return "Hello, " + super.name;
    }
}
  • 子类引用父类的字段时,可以用super.fieldNamethis.fieldNamefieldName的形式来引用。
  • 某些时候就必须使用super,如果父类没有默认的构造方法,子类就必须显式调用super()

向上转型与向下转型

向上转型

  • 如果一个引用变量的类型是Student,那么它可以指向一个Student类型的实例:
    Student s = new Student();
  • 如果一个引用类型的变量是Person,那么它可以指向一个Person类型的实例:
    Person p = new Person();
  • 把一个子类类型安全地变为父类类型的赋值,被称为向上转型
Student s = new Student();
Person p = s; // upcasting, ok
Object o1 = p; // upcasting, ok
Object o2 = s; // upcasting, ok

继承树是Student > Person > Object,所以,可以把Student类型转型为Person,或者更高层次的Object

向下转型

  • 向上转型相反,如果把一个父类类型强制转型为子类类型,就是向下转型
Person p1 = new Student(); // upcasting, ok
Person p2 = new Person();
Student s1 = (Student) p1; // ok
Student s2 = (Student) p2; // runtime error! ClassCastException!

多态

多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。

public class Main {
    public static void main(String[] args) {
        // 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
        Income[] incomes = new Income[] {
            new Income(3000),
            new Salary(7500),
            new StateCouncilSpecialAllowance(15000)
        };
        System.out.println(totalTax(incomes));
    }

    public static double totalTax(Income... incomes) {
        double total = 0;
        for (Income income: incomes) {
            total = total + income.getTax();
        }
        return total;
    }
}

class Income {
    protected double income;

    public Income(double income) {
        this.income = income;
    }

    public double getTax() {
        return income * 0.1; // 税率10%
    }
}

class Salary extends Income {
    public Salary(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        if (income <= 5000) {
            return 0;
        }
        return (income - 5000) * 0.2;
    }
}

class StateCouncilSpecialAllowance extends Income {
    public StateCouncilSpecialAllowance(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        return 0;
    }
}

  • 利用多态,totalTax()方法只需要和Income打交道,它完全不需要知道SalaryStateCouncilSpecialAllowance的存在,就可以正确计算出总的税。如果我们要新增一种稿费收入,只需要从Income派生,然后正确覆写getTax()方法就可以。把新的类型传入totalTax(),不需要修改任何代码。

抽象类

  • 由于多态的存在,每个子类都可以覆写父类的方法
class Person {
    public void run() { … }
}

class Student extends Person {
    @Override
    public void run() { … }
}

class Teacher extends Person {
    @Override
    public void run() { … }
}

Person类派生的StudentTeacher都可以覆写run()方法。

  • 如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。
  • 当我们定义了抽象类Person,以及具体的Student、Teacher子类的时候,我们可以通过抽象类Person类型去引用具体的子类的实例

后言

学到这,我回头看去,我已经不知道我在学些什么了,我觉得从面对对象编程开始,我就开始迷糊,不知道学的是什么,只是一味的死记住,并不知道怎么用,看着他说的一大片话只是懵懂,有时候看着看着都能发呆,导致这周也没去学些啥,因为不知道在学些啥,我打算要换个方向去学习java了,想去看有讲解的视频去继续学习。

上一篇:Reading27. Income Taxes


下一篇:wz26