关于面向对象编程

暑假预习Java,这里总结下面向对象中Java和C++一些不一样的地方

super();

class person {
    protected int age;

    public person(int age) {
        this.age = age;
    }
}

class student extends person {
    protected int score;

    public student(int age,int score) {
        //super(age);
        this.score = score;
    }
}

如果没有使用super,会得到一个编译错误,在student的构造方法中,无法调用person的构造方法

在java里,任何class的构造方法,第一行必须调用父类的构造方法,如果没有明确地调用父类的构造方法,编译器会自动加一句super();,but,这个super里没有参数,父类里没有无参数的构造方法,故编译失败,因此,需要把注释去掉,加上正确的super语句

阻止继承

官方版

aa.java

public final class aa{/* code */}

final来修饰指定类

bb.java

public class bb extends aa{/* code */}

编译完第一个类后再编译第二个类,JDK编译器会报错,编译器会在extends处提示错误

非官方版

aa.java

public class aa{
    private aa(){/**/}
    public static aa fun(){
        return new aa();
    }
}

Java在继承时必须在构造器里的第一行调用super class的构造器。当父类构造器设为private权限时,其他类继承这个类时,编译器会尝试调用一个默认的super构造器,而super构造器时private的,就不能被调用,也就是不能被继承。

多态

aa.java

public class aa{
    public static void main(String[] args){
        person p = new student();
        p.run();
        //result: student.run
    }
}
class person{
    public void fun(){
        System.out.println("person.run");
    }
}
class student{
	@override
    //override后面不要加分号
    public void fun(){
        System.out.print("student.run");
    }
}

下面是一个报税的例子

public class aa {
    public static void main(String[] args) {
        income[] incomes = new income[] { new income(3000), new salary(7000), new allowance(10000) };
        System.out.println(totalTax(incomes));
        //打印的结果是income,salary,allowance折扣后的总值
    }

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

class income {
    //收入
    protected double in;

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

    public double getTax() {
        return in * 0.1;
    }
}

class salary extends income {
    //工资
    public salary(double in) {
        super(in);
    }
    @Override
    public double getTax() {
        if (in <= 5000)
            return 0;
        return (in-5000)*0.2;
    }
}

class allowance extends income {
    //特殊津贴
    public allowance(double in) {
        super(in);
    }
    @Override
    public double getTax() {
        return 0;
    }
}

调用super

class person{
    protected String name;
    public String hello(){
        return "hello, " + name;
    }
}
class student extends person{
    @override
    public String hello(){
        //调用父类的hello()方法
        return super.hello() + "!";
    }
}

final

class aa{
    public final String fun(){/**/}
}
class bb{
	@override
    public String fun(){/**/}
    //父类成员用final修饰,子类不能重写
    //final修饰类,类不能被继承,final修饰变量,变量必须初始化
}

抽象类

//定义一个抽象类
class person{
    public abstract void fun();
}

把一个方法声明为abstract,提示编译错误,无法编译person类,因为它包含抽象方法,所以必须把person也声明为abstract,这就叫抽象类

abstract class person{
    public abstract void fun();
}

但是,对于person类,我们无法使他实例化,即在main中执行person p = new person();

因此,抽象类一般被设计来继承

public class aa {
    public static void main(String[] args) {
        person p = new student();
        person t = new teacher();
        p.fun();
        t.fun();
    }
}
abstract class person {
    public abstract void fun();
}
class student extends person {
    @Override
    public void fun() {
        System.out.println("student.fun");
    }
}
class teacher extends person{
    @override
    public void fun(){
        System.out.println("teacher.fun");
    }
}

如上例子,person定义了抽象方法fun(),那么在实现子类时,就必须覆写run()

面向对象编程

刚才定义了抽象类person(),以及具体的student、teacher的子类,我们可以通过抽象类person去引用具体的子类

person s = new student();
person t = new teacher();

这种引用抽象类的好处在于,我们调用其方法,并不关心person类型变量的具体子类型

s.fun();
t.fun();

同样的,我们再用用一个新的子类,我们仍不关心具体类型。

因此,这种尽量引用高层类型,避免引用实际子类型的方式,叫面向对象编程

三个本质

  • 上层代码只定义规范(例如abstract class person;);
  • 不需要子类就可以实现业务逻辑(正常编译)
  • 实现的业务逻辑由不同的子类实现,调用者并不关心

一个java文件里只能有一个public类

感觉我的面向对象编程是在Java里学的