12 抽象类、多态、根父类

lix_uan
• 阅读 1101

抽象类

定义

  • 抽象类:被abstract所修饰的类
  • 抽象方法:没有方法体的方法
  • 包含抽象方法的类必须是抽象类

注意事项

  • 抽象类不能创建对象
  • 抽象类中可以有构造方法。供子类创建对象时,初始化父类成员使用
  • 抽象类中不一定包含抽象方法,但有抽象 方法的类一定时抽象类
  • 继承抽象类的子类必须重写父类的所有抽象方法

抽象类的练习

public abstract class Person {
    public abstract void walk();
    public abstract void eat();
}
public class Man extends Person {

    @Override
    public void walk() {
        System.out.println("大步流星走路");
    }

    @Override
    public void eat() {
        System.out.println("狼吞虎咽吃饭");
    }

    public void smoke(){
        System.out.println("吞云吐雾");
    }
}

多态

  • 定义:同一行为,具有多个不同表现形式

前提

  • 继承父类或者实现接口
  • 方法的重写
  • 父类引用指向子类对象

多态的体现

  • 编译看父类
    • 只能调用父类声明的方法,不能调用子类扩展的方法
  • 运行看子类
    • 一定是执行子类重写的方法体

多态的练习

public abstract class Employee {
    private String name;

    public Employee(String name) {
        super();
        this.name = name;
    }

    public Employee() {
        super();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract double earning();

    public String getInfo() {
        return "姓名:" + name + ",实发工资:" + earning();
    }
}
public class SalaryEmployee extends Employee {
    private double salary;
    private int workingDays;//工作日天数,
    private double offDays;//请假天数

    public SalaryEmployee() {
        super();
    }

    public SalaryEmployee(String name,  double salary, int workingDays, double offDays) {
        super(name);
        this.salary = salary;
        this.workingDays = workingDays;
        this.offDays = offDays;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public int getWorkingDays() {
        return workingDays;
    }

    public void setWorkingDays(int workingDays) {
        this.workingDays = workingDays;
    }

    public double getOffDays() {
        return offDays;
    }

    public void setOffDays(double offDays) {
        this.offDays = offDays;
    }

    /*
     * 重写方法,public double earning()返回实发工资, 
        实发工资 = 薪资 - 薪资/工作日天数 * 请假天数
     */
    @Override
    public double earning() {
        return salary - salary/workingDays * offDays;
    }

}
public class HourEmployee extends Employee {
    private double moneyPerHour;
    private double hours;

    public HourEmployee() {
        super();
    }

    public HourEmployee(String name, double moneyPerHour, double hours) {
        super(name);
        this.moneyPerHour = moneyPerHour;
        this.hours = hours;
    }

    public double getMoneyPerHour() {
        return moneyPerHour;
    }

    public void setMoneyPerHour(double moneyPerHour) {
        this.moneyPerHour = moneyPerHour;
    }

    public double getHours() {
        return hours;
    }

    public void setHours(double hours) {
        this.hours = hours;
    }

    /*
     * 重写方法,public double earning()返回实发工资, 
        实发工资 = 每小时多少钱 * 小时数    
     */
    @Override
    public double earning() {
        return moneyPerHour * hours;
    }
}
public class Manager extends SalaryEmployee {
    private double commisionPer;

    public Manager() {
        super();
    }

    public Manager(String name,  double salary, int workingDays, double offDays, double commisionPer) {
        super(name, salary, workingDays, offDays);
        this.commisionPer = commisionPer;
    }

    public double getCommisionPer() {
        return commisionPer;
    }

    public void setCommisionPer(double commisionPer) {
        this.commisionPer = commisionPer;
    }

    @Override
    public double earning() {
        return super.earning() * (1+commisionPer);
    }
}
public class TestEmployee {
    public static void main(String[] args) {
        Employee[] all = new Employee[3];

        all[0] = new HourEmployee("张三", 50, 50);
        all[1] = new SalaryEmployee("李四", 10000, 22, 1);
        all[2] = new Manager("老王", 20000, 22, 0, 0.3);

        double sum = 0;
        for (int i = 0; i < all.length; i++) {
            System.out.println(all[i].getInfo());
            sum += all[i].earning();
        }
        System.out.println("总额:" + sum);
    }
}

父子类之间的类型转换

向上转型

  • 多态本身是子类类型向父类类型转换的过程,这个过程是默认的

向下转型

  • 父类类型向子类类型转换的过程,这个过程是强制的

为什么要转型

  • 多态为了调用子类特有的方法

类型转换异常: ClassCastException

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        Dog d = (Dog)a;       
        d.watchHouse();        // 调用的是 Dog 的 watchHouse 【运行报错】
    }  
}

instanceof运算符

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}

属性、静态方法没有多态性

属性没有多态性

  • 如果直接访问成员变量,那么只看编译时类型

    public class TestField {
        public static void main(String[] args) {
            Father f = new Son();
            System.out.println(f.x);//只看编译时类型 x=1
        }
    }
    class Father{
        int x = 1;
    }
    class Son extends Father{
        int x = 2;
    }

静态方法没有多态性

public class TestField {
    public static void main(String[] args) {
        Father f = new Son();
        f.test();//只看编译时类型
    }
}
class Father{
    public static void test(){
        System.out.println("father");
    }
}
class Son extends Father{
    public static void test(){
        System.out.println("son");
    }
}

native关键字

  • native:本地的、原生的
  • 只能修饰方法,表示这个方法的方法体代码不是用Java语言实现的

修饰符一起使用的问题

不能和abstract一起使用的修饰符

  • final:和final不能一起修饰方法和类
  • static:和static不能一起修饰方法
  • private:和private不能一起修饰方法

static和final一起使用

  • 修饰方法:可以,因为都不能被重写
  • 修饰成员变量:可以,表示静态常量
  • 修饰局部变量:不可以,static不能修饰局部变量
  • 修饰代码块:不可以,final不能修饰代码块
  • 修饰内部类:可以一起修饰成员内部类,不能一起修饰局部内部类

Object根父类

public String toString():

public class Person {  
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }

    // 省略构造器与Getter Setter
}

public final Class<?> getClass():获取对象的运行时类型

public static void main(String[] args) {
    Object obj = new String();
    System.out.println(obj.getClass());//运行时类型
}

public int hashCode():返回每个对象的hash值

public static void main(String[] args) {
    System.out.println("Aa".hashCode());//2112
    System.out.println("BB".hashCode());//2112
}

public boolean equals(Object obj):

  • 用于判断当前对象this与指定对象obj是否“相等”
  • 默认情况下等价于“==”,比较的是对象的地址值
  • 可以重写,但一定要一起重写hashCode()方法
点赞
收藏
评论区
推荐文章

暂无数据

lix_uan
lix_uan
Lv1
学无止境,即刻前行
文章
7
粉丝
7
获赞
0