java学习-多态抽象类接口

Posted zcb_bai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java学习-多态抽象类接口相关的知识,希望对你有一定的参考价值。

一、多态

  1.1 多态的概述

  1. 多态是面向对象一大特征
  2. 多态 : 表示事物的多种形态(事物的多种表现形式)
  3. 多态发生的前提:

    1) 需要具有子父类的继承关系(类与接口实现关系)

    2) 子类重写从父类继承来的方法

    3) 父类的引用指向子类的对象

  举例 :

    class Person{}

    class Doctor extends Person{}

    class Teacher extends Person{}

  多态表达式:

    Person p;  // 父类引用

    new Doctor(); // 子类对象

    new Teacher() ;// 子类对象

    Person p = new Doctor(); // 人类p的表现形式是医生

    Person p1 = new Teacher(); // 人类p1的表现形式是教师

    以上表达式能体现出人类的多种表现形式,这就是多态的概念

代码

public class Person {
    public void eat() {
        System.out.println("人都需要吃饭");
    }
}
public class Doctor extends Person {
    @Override
    public void eat() {
        System.out.println("医生吃的比较清淡");
    }
}
public class Teacher extends Person {
    @Override
    public void eat() {
        System.out.println("教师今天想吃凉皮");
    }
}
public class TestDuoTai {
    public static void main(String[] args) {
        // 多态表达式
        Person p = new Doctor();
        p.eat();// 医生吃的比较清淡
        
        Person p1 = new Teacher();
        p1.eat();// 教师今天想吃凉皮
    }
}

  1.12多态中成员方法的特点

  1. 编译看左,运行看右

  使用多态表达式调用成员方法

    1) 编译看左 : 编译代码时, 如果多态表达式调用的这个方法, 在  等号的左边的类型中不存在(没定义), 那么直接报错,无法编译通过. 如果等号左边的类型中存在调用的方法,编译成功

    2) 运行看右 : 使用多态的表达式调用方法,运行时动态绑定等号右边的类型中的方法实现, 实际运行的就是等号右边子类中的重写方法

代码

 

public class Person {
    public void eat() {
        System.out.println("人都需要吃饭");
    }
}

 

public class Doctor extends Person {
    @Override
    public void eat() {
        System.out.println("医生吃的比较清淡");
    }
    
    // 医生特有的救人功能
    public void savePerson() {
        System.out.println("医生可以治病救人");
    }
}
public class Teacher extends Person {
    @Override
    public void eat() {
        System.out.println("教师今天想吃凉皮");
    }
    
    // 老师特有功能授课
    public void teach() {
        System.out.println("老师可以授课");
    }
}
public class TestDuoTai {
    public static void main(String[] args) {
        // 多态表达式
        // 1. 编译看左,运行看右
        Person p = new Doctor();
        // eat方法在等号左边的类型Person中存在(定义)
        p.eat();//医生吃的比较清淡
        // savePerson方法在等号左边的类型Person中不存在,因此报出编译错误
        // p.savePerson(); //The method savePerson() is undefined for the type Person
        
        Person p1 = new Teacher();
        p1.eat();//教师今天想吃凉皮
        // p1.teach();
    }
}

  1.3多态的向上和向下转型

  1. 多态向上转型 : 父类的引用指向子类对象(多态表达式)

  Person p = new Doctor();

  向上转型的实质 : 对象引用p使用范围缩小, 只能使用子父类中的共有方法

  2.多态向下转型 :

  目的 : 为了解决多态表达式中,无法使用子类特有方法的局限性, 想要使用子类中的特有方法功能

  多态向下转型公式: 将指向子类对象的父类引用, 恢复成子类类型

  举例 :  Doctor d = (Doctor)p;

  向下转型实质 : 对象引用p使用范围变大, 可以使用子类中的内容

  1.4 多态的好处

  1. 多态好处 : 提高代码的扩展性
  2. 方法的参数列表上 : 定义一个方法功能, 形式参数可以是父类数据类型, 在方法中可以使用父类参数中的任意功能; 当调用这个方法时, 实际参数可以是当前父类类型对象本身,也可以是这个父类的任意一个子类类型对象
  3. 一个类型不一定非通过new对象才能创建, 很多情况下, 方法功能返回值类型就是引用数据类型, 需要一个对应的引用类型接方法返回值, 若这个引用的具体类型不清楚,可以直接使用一个父类类型作为这个方法的返回值类型承接

需求 : 现有一农场,需要设计出一个方法, 功能是提供不同的动物类型,能输出每一种动物需要投喂的食物, 请根据多态设计出这个方法功能

举例 : 给该方法传递猫类型数据 : 提示, 喂鱼 ; 给该方法传递狗类型数据 : 提示 , 吃骨头; 给该方法传递羊类型数据 : 提示 , 喂草 .... 每一种动物都能得到对应的喂食结果

 代码

 

public class Animal {
     // 将所有动物都需要喂食功能 : eat
     public void eat() {
         System.out.println("所有动物都需要喂食");
     }
}

 

public class Cat extends Animal {
         @Override
         public void eat() {
             System.out.println("猫喂鱼");
         }
}
public class Dog extends Animal {
     @Override
     public void eat() {
         System.out.println("狗喂骨头");
     }
}
public class Farmer {
     // 方法功能 : 将每一种动物喂食结果显示出来
     public void wei(Animal a) {// Animal a = new Sheep();
         a.eat();
     }
     
     public void useI(int i) {// int i = 10;
         System.out.println(i);
     }
}

二、 抽象类

  2.1 抽象方法和抽象类

  1. 抽象 : 表示无法使用语言进行描述, 无法实现的, 虚无缥缈,没有具体存在

     将事物的共性向上抽取,抽取到父类中, 但是当共性抽取到一定程度时, 父类中不知道如何实现共性内容才能让每一个子类都满足实际需求, 于是父类中将共性方法只做方法的声明,而没有方法的实现,这样的方法称为抽象方法

  2.抽象方法的定义:

    需要使用关键字 : abstract

    修饰符 abstract 返回值类型 方法名(参数列表);

  3.抽象类的定义:

    修饰符 abstract class 类名{

       // 抽象方法只能存在于抽象类中

    }

  4.抽象方法存在是为了为子类限定一些需要实现的规则

代码

 

public abstract class Animal {

    // 抽象方法
    // The abstract method eat in type Animal can only be defined by an abstract class
    // 抽象方法只能定义在抽象类中
    public abstract void eat();
}

 

2.2 抽象的特点

  1. 抽象类和抽象方法都需要使用 abstract 抽象关键字

    public abstract class Animal{

       public abstract void eat();

    }

  2.抽象类和抽象方法之间的关系:

    1) 抽象方法必须定义在抽象类中

    2) 抽象类中可以没有抽象方法

  3.抽象类的实例化(实例化 : new对象)

    1) 抽象类不能实例化对象(不能new对象)

     因为抽象类中可以含有抽象方法, 而抽象方法因为没有方法体,不能运行的,因此抽象类不能new对象

    2) 抽象类等着当父类,等着被子类继承, 需要一个子类继承这个抽象类, 让子类将抽象父类中的所有抽象方法全部重写, 通过创建子类对象,实现方法的调用

  4.抽象类的子类前途:

    1) 子类将抽象父类中的所有抽象方法全部重写, 子类可以正常创建对象使用

    2) 子类没有将抽象父类中的所有抽象方法全部重写, 子类仍然还是一个抽象类

   2.3抽象类中的成员

    抽象类中的成员 : 先把抽象类当做一个普通类, 在此基础上可以定义抽象方法

   1.可以定义成员变量

  2.可以定义构造方法

     一个类型是否可以定义构造方法,与这个类型能否创建对象无关, 与类型中是否能定义成员变量有关. 只要一个类型中可以定义成员变量,那么这个类型就可以定义构造方法

  3.可以定义非抽象方法

     为了给子类直接继承使用

  4.可以定义抽象方法

     为了给子类限定需要实现的规则

抽象的练习 :

  每个员工Employee都具有属性(姓名,工号,工资),行为 : 工作

    程序员类: 属性(姓名,工号,工资,奖金), 行为 : 工作(软件开发)

  测试工程师类 : 属性(姓名,工号,工资), 行为 : 工作(软件测试)

  项目经理类 : 属性(姓名,工号,工资,奖金),行为 : 工作(控制工作进度)

   请设计出合适的类关系,并测试
代码

public abstract class Employee {
    // 姓名,工号,工资
    private String name;
    String id;
    double salary;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public abstract void work();
}
public class Employee_程序开发 extends Employee{    
    private double jiangjin;    

    public Employee_程序开发(String name , String id, double salary, double jiangjin) {
        super();
        this.jiangjin = jiangjin;
        this.id = id;
        setName(name);
        this.salary = salary;
    }
    
    public Employee_程序开发() {
        super();
    }

    public double getJiangjin() {
        return jiangjin;
    }

    public void setJiangjin(double jiangjin) {
        this.jiangjin = jiangjin;
    }

    @Override
    public void work() {
    System.out.println(getName() +"---"+ id +"---"+ salary + "---"+jiangjin+"程序员做开发");
    }

}
public class Employee_测试工程师 extends Employee{

    @Override
    public void work() {
        System.out.println("测试工作");
    }
}
public class TestEmployee {

    public static void main(String[] args) {
        Employee_程序开发 e1 = new Employee_程序开发("小张","007",15678.99,3200);
        e1.work();    
        Employee_测试工程师 e2 = new Employee_测试工程师();
        e2.work();
    }
}

三、接口

  3.1 接口的概述

  1. 接口 : 一系列规则的集合, 接口中都是抽象方法
  2. 接口好处:

   因为接口中全部都是抽象方法, 抽象方法只方法的声明, 方法功能的声明和方法的实现分离, 让类型与类型之间的耦合度(关联度)降低

  3.2 接口的定义

  1. 接口的定义 :

  使用关键字 interface : 用于定义出接口类型

  修饰符  interface 接口名{

        // 抽象方法(随着JDK版本的推进, 接口中不仅仅只有抽象方法,目前学习中,以抽象方法为学习重点,JDK8新特性,讲解接口中的其他方法定义)

}

代码

public interface MyInter {
    // 定义抽象方法
    public abstract void fun();
    
    public abstract boolean equalDouble(double d, double d1);
}

  3.3 接口的特点

  1. 接口中的方法都是抽象方法
  2. 接口不能实例化对象(不能new对象)

   接口需要一个实现类, 将接口中的所有抽象方法重写,通过创建实现类对象,调用重写方法

  3.类与接口之间的关系:实现关系 implements (与类和类之间的继承extends关系非常相似)

  举例 : interface MyInter{}

       class MyInterImpl implements MyInter{

            // 将接口中的抽象方法全部重写;

}

  4.接口实现类的前途:

    1) 如果实现类将接口中的所有抽象方法全部重写,那么这个实现类可以正常使用

    2) 如果实现类没有将接口中的所有抽象方法全部重写, 那么这个实现类是抽象类, 抽象类不能实例化对象

  3.4接口中的成员

  1. 成员常量 : 接口中的所有成员变量都是常量, 因为接口中的成员变量有默认修饰, public static final, 写出修饰或者不写,以及写出修饰符的一部分, 默认修饰不变
  2. 接口中无法定义构造方法: 因为接口中没有成员变量
  3. 抽象方法 : 有默认修饰符, public abstract 

 

以上是关于java学习-多态抽象类接口的主要内容,如果未能解决你的问题,请参考以下文章

java学习-多态抽象类接口

Java学习笔记3.7.3 抽象类接口与多态 - 多态

Java学习笔记3.7.2 抽象类接口与多态 - 接口

No_16_0229 Java基础学习第九天

2019-05-17 Java学习日记之面向对象_多态&抽象类&接口

Java基础学习191221(可变参数,数组,Array类,稀疏数组,继承重写多态,抽象类,接口)