02-JavaSE【多态、修饰符、接口】


利用面向对象思想完成"考试系统"案例

分析:

  • 概念模型(事物)

    • Java学生
      • 属性:姓名、年龄、班级、学号、…
      • 行为:登录()、考试()
    • UI学生
      • 属性:姓名、年龄、班级、学号、…
      • 行为:登录()、考试()
  • 把概念模型中的共性内容,向上抽取,封装为:父类

    • 父类:Student
      • 属性:姓名、年龄、班级、学号
      • 行为:登录()、考试()

一、多态

01_多态:多态的概述(了解)

目标

  • 了解多态的基本概念

路径

  1. 多态的含义
  2. 使用多态的前提
  3. 多态的书写格式

多态的含义

面向对象的三个特性:

  • 封装
  • 继承(是建立封装的基础之上)
  • 多态(是建立在继承的基础之上)

什么是多态?

  • 事物的多种展现形态

  • 举例: 数值:10

    • 2进制表示形式:1010
    • 10进制表示形式:10
    • 8进制表示形式:12
    • 16进制表示形式:A

多态的前提

在使用多态的前提条件:

  • 有继承关系(学习接口后有实现关系)

  • 子类重写父类中的方法

多态的书写格式

书写格式:父引用指向子类对象

父类 父引用 = new 子类();

创建子类对象:
    方式1:  JavaStudent  javaStu = new JavaStudent(); //使用事物的本身类型来定义
    方式2:  Student      stu     = new JavaStudent(); //使用事物的父类型来定义
//父类
abstract class Student{
    //属性
    private String name;
    
    //行为
    public abstract void exam();//抽象方法
    
    //getter、setter
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}
//子类
class JavaStudent extends Student{
    //重写抽象方法
    public void exam(){
        System.out.println("java学员,进行阶段考试")
    }
}

//测试类
public static void main(String[] args){
    //可以使用事物本身类型来定义
    JavaStudent javaStu = new JavaStudent();
    
    //可以使用事物的父类型来定义
    Student stu = new JavaStudent();//父引用指向子类对象
    
    //Student :   父类型
    //stu :    父引用(父类对象)
    //new JavaStudent() : 子类对象
}

小结

  • 多态的概念:事物的多种展现形式

  • 多态的代码格式:

    • 父类  父对象  = new 子类();
      //父对象引用了子类对象
      
02_多态:多态体现(了解)

目标

  • 了解多态的体现方式

路径

  1. 多态的体现方式

多态的体现方式

在Java语言中,多态的体现划分为两类:

  • 静态多态
    • 也称为编译期多态
    • 概念:同一个对象的不同行为体现
      • 举例:同一个对象进行登录,可以有不同的登录方式(用户名/密码、手机验证码、人脸识别)
      • 代码体现为:方法重载
  • 动态多态
    • 也称为运行期多态

    • 概念:不同对象的相同行为体现

      • 举例:不同的对象进行考试,对象都有考试功能(Java学生=>考试、UI学生=>考试)
    • 代码体现为:方法重写

      • 有继承关系(学习接口后有实现关系)
      • 子类重写父类中的方法

小结

在java中多态的体现可以划分为:

  • 静态多态:同一个对象的不同行为
    • 代码实现:方法重载
  • 动态多态:不同对象的相同行为
    • 代码实现:方法重写
03_多态:静态多态

目标

  • 清楚静态多态的使用方式

路径

  1. 案例分析

  2. 代码实现


案例分析

为"考试系统",开发登录功能,登录方式有3 种:

  • 用户名/密码
  • 手机验证码
  • 人脸识别

思考:

  • 学生登录
  • 登录有3种形式:开发3个方法

代码实现

静态多态:

  • 同一个对象的不同行为体现 (重载)
//父类
public abstract class Student {
    private String number;//学号
    private String name;//姓名
    private int age;//年龄
    private String classes;//班级

    public Student() {
    }
    public Student(String number, String name, int age, String classes) {
        this.number = number;
        this.name = name;
        this.age = age;
        this.classes = classes;
    }

    //登录
    public abstract boolean login(String name,String passwd);
    public abstract boolean login(int phoneCode);
    public abstract boolean login(String face);

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getClasses() {
        return classes;
    }

    public void setClasses(String classes) {
        this.classes = classes;
    }
}

//子类:Java学生
public class JavaStudent extends Student{
    public JavaStudent() {
    }
    public JavaStudent(String number, String name, int age, String classes) {
        super(number, name, age, classes);
    }

   
    /**
     * 登录:用户名和密码
     * */
    @Override
    public boolean login(String name,String passwd){
        Scanner sc = new Scanner(System.in);
        System.out.print("用户名:");
        String loginName = sc.next();
        System.out.print("密码:");
        String loginPwd =sc.next();

        return true;
    }


    /**
     * 登录:手机验证码
     * */
    @Override
    public boolean login(int phoneCode){
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入手机验证码:");
        int pc = sc.nextInt();
        
        return true;
    }

    /**
     * 登录:人脸识别
     * */
    @Override
    public boolean login(String face){
        System.out.print("请不要动,人脸识别中...");
        
        return true;
    }
}

//考试系统
public class ExamSys {
    public static void main(String[] args) {
        init();
    }
    
    public static void init() {
        System.out.println("******************考试系统******************");
        System.out.println("请选择学科: 1) Java \t 2) UI");
        int subjectNumber = new Scanner(System.in).nextInt();
        switch (subjectNumber) {
            case 1:
                JavaStudent javaStu = new JavaStudent();
                //考试前:先登录
                if (login(javaStu)) {
                    System.out.println("登录成功!");
                    // TODO: 未完成的功能
                }
                break;
            case 2:
                UiStudent uiStu = new UiStudent();
                if (login(uiStu)) {
                    System.out.println("登录成功!");
                    // TODO: 未完成的功能
                }
                break;
            default:
                System.out.println("选择错误,退出系统!");
                System.exit(0);
        }

    }

    //登录
    public static boolean login(Student stu) {
        System.out.println("---------------------------------------------");
        System.out.println("请选择登录方式:");
        System.out.println("1、用户名/密码");
        System.out.println("2、手机验证码");
        System.out.println("3、人脸识别");
        int loginNumber = new Scanner(System.in).nextInt();
        System.out.println("---------------------------------------------");
        boolean result = false;
        switch (loginNumber) {
            case 1:
                result = stu.login("用户名", "密码");
                break;
            case 2:
                result = stu.login(40088);
                break;
            case 3:
                result = stu.login("人脸数据");
                break;
        }
        return result;
    }
}

小结

静态多态:同一个对象,不同行为的展现

实现方式:方法重载(在一个类中)

04_多态:动态多态(重点)

目标

  • 掌握动态多态的使用方式

路径

  1. 案例分析

  2. 代码实现


案例分析

为"考试系统",开发考试功能:

  • Java学生 => 考试

  • UI学生 => 考试

方法中除了对象不同外,其它代码都是类同(复用性很差)

解决方案:多态(动态多态)

代码实现:方法重写

  • Student stu1 = new JavaStudent();//多态的格式
    Student stu2 = new UiStudent();
    
    stu1.exam();//因为Student类中有exam()方法,所以可以调用
               //在执行时,因为JavaStudent类重写了exam()方法,所以执行时使用重写后的方法
    
    stu2.exam();//运行时调用UiStudent类中重写的exam()方法
    

    思考:JavaStudent和UiStudent中有没有exam()方法?

    答案:使用动态多态解决程序中复用性的问题

public void startExam(Student stu){
    stu.exam();
}

代码实现

动态多态:

  • 不同对象的相同行为体现 (重写)
//父类:学生
public abstract class Student {
    private String number;//学号
    private String name;//姓名
    private int age;//年龄
    private String classes;//班级

    public Student() { }
    public Student(String number, String name, int age, String classes) {
        this.number = number;
        this.name = name;
        this.age = age;
        this.classes = classes;
    }

    //考试
    public abstract void exam();
    //登录
    public abstract boolean login(String name,String passwd);
    public abstract boolean login(int phoneCode);
    public abstract boolean login(String face);

    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getClasses() {
        return classes;
    }
    public void setClasses(String classes) {
        this.classes = classes;
    }
}

//子类:Java学生
public class JavaStudent extends Student{
    public JavaStudent() { }
    public JavaStudent(String number, String name, int age, String classes) {
        super(number, name, age, classes);
    }

    /**
     * 考试
     */
    @Override
    public void exam() {
       System.out.println("Java学生,进行阶段性考试!");
    }

    /**
     * 登录:用户名和密码
     * */
    @Override
    public boolean login(String name,String passwd){
        Scanner sc = new Scanner(System.in);
        System.out.print("用户名:");
        String loginName = sc.next();
        System.out.print("密码:");
        String loginPwd =sc.next();

        return true;
    }

    /**
     * 登录:手机验证码
     * */
    @Override
    public boolean login(int phoneCode){
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入手机验证码:");
        int pc = sc.nextInt();
        return true;
    }

    /**
     * 登录:人脸识别
     * */
    @Override
    public boolean login(String face){
        System.out.print("请不要动,人脸识别中...");
        return true;
    }
}

//考试系统
public class ExamSys {
    public static void main(String[] args) {
        init();
    }

    public static void init() {
        System.out.println("******************黑马考试系统******************");
        System.out.println("请选择学科: 1) Java \t 2) UI");
        int subjectNumber = new Scanner(System.in).nextInt();
        switch (subjectNumber) {
            case 1:
                JavaStudent javaStu = new JavaStudent();
                //考试前:先登录
                if (login(javaStu)) {
                    System.out.println("登录成功!");
                    
                    //多态的体现:传递的是子类对象
                    startExam(javaStu);
                }
                break;
            case 2:
                UiStudent uiStu = new UiStudent();
                if (login(uiStu)) {
                    System.out.println("登录成功!");
                    
                    //多态的体现:传递的是子类对象
                    startExam(uiStu);
                }
                break;
            default:
                System.out.println("选择错误,退出系统!");
                System.exit(0);
        }
    }

    //登录
    public static boolean login(Student stu) {
        System.out.println("---------------------------------------------");
        System.out.println("请选择登录方式:");
        System.out.println("1、用户名/密码");
        System.out.println("2、手机验证码");
        System.out.println("3、人脸识别");
        int loginNumber = new Scanner(System.in).nextInt();
        System.out.println("---------------------------------------------");
        boolean result = false;
        switch (loginNumber) {
            case 1:
                result = stu.login("用户名", "密码");
                break;
            case 2:
                result = stu.login(40088);
                break;
            case 3:
                result = stu.login("人脸数据");
                break;
        }
        return result;
    }

     /**
     * 开始考试
     * @param stu 父类引用作为形参
     */
    public static void startExam(Student stu) {
        System.out.println("*****************考试题****************");
        stu.exam();
    }
}

小结

动态多态的书写方式: 父类 父对象 = new 子类();

动态多态在开发中的应用场景:

  • 方法中参数多态

  • 方法返回值多态

    • //返回值多态   
      //返回类型为:Student类型(父类型)
      public Student createObject(int flag , String name,int age){
       
          if(flag ==1){
              //实例化子类对象
              return new JavaStudent(name,age);//返回子类对象
          }else if (flag ==2 ){
              return new UiStudent(name,age);
          }
      }
      

多态的好处:提高程序中代码的复用性、扩展性

05_多态:多态中方法的执行特点(了解)

目标

  • 能够理解在多态中方法执行特点

路径

  1. 成员方法在多态中的执行特点
  2. 代码验证

说明:

成员变量不参与多态,只有成员方法才有多态现象

成员方法在多态中的执行特点

  • 多态的格式调用方法,指的是使用父类型调用方法
    • 方法执行时,会执行子类重写的方法
    • 如果子类没有重写方法,会向父类找到方法执行
      • 前提:父类中不是抽象方法(父类的方法有具体的代码实现)
  • 使用多态形式调用方法,不能调用子类中特有的方法(多态的弊端)

结论:在多态中,父引用只能调用子类和父类中共有的方法

  • 父引用 可以调用父类自己的方法

案例代码(验证多态中方法的特点)

public class JavaStudent extends Student {

    public JavaStudent() {
    }
    public JavaStudent(String number, String name, int age, String classes) {
        super(number, name, age, classes);
    }

    @Override
    public void exam() {
        System.out.println("-----------------------------------------------------");
        System.out.println("java学生,在进行阶段考试!");
    }


    //子类特有的功能
    public void project(){
        System.out.println("java学生,在紧张的进行项目实践.....");
    }
   }


public static void startExam(Student stu){
        System.out.println("******************XXXXX学科考试题***************");
        //不同对象的相同行为
        stu.exam();//调用不同学生对象中的考试方法

        //stu.project();//父类对象不能调用子类中特有的方法


        System.out.println("--------------------------------------------------");
    }

小结

  • 多态中父引用调用的方法,是指父类中的方法
    • 在多态中会检查 父类中的方法是否存在,不存在时:报错
  • 多态调用方法时:
    • 子类重写了父类中的方法,执行重写后的方法
    • 子类没有重写父类中的方法,执行时会去父类中找相关方法执行
  • 多态的弊端
    • 父引用无法调用子类中特有的方法
06_多态:多态的类型转换

目标

  • 掌握引用数据类型的向下转型方式

路径

  1. 向上转型
  2. 向下转型

前言

在学习基本数据类型时,有讲过一个知识点:基本数据类型转换

  • 隐式转换:小类型自动转换为大类型(不需要书写代码)
  • 强制转换:大类型强制转换为小类型(需要手动书写代码)
    • 格式:小类型 变量 = (小类型) (大类型数据)

引用类型:数组、String、类、接口

引用类型的转换:

  • 向上转型(小类型转大类型)【自动完成,不需要书写代码】
  • 向下转型(大类型转小类型)

向上转型

在书写多态代码时,就已经实现向上转型

Student stu = new UiStudent();//UiStudent类型转换为Student类型(类型提升)

注意:stu引用的是子类对象,虽然类型向上转型了,但底层实际还是子类

向下转型

多态的弊端:父引用无法调用子类特有的方法

  • 解决方案:使用多态的向下转型

向下转型的书写格式: 子类 子类对象 = (子类) 父引用

//多态体现:向上转型
Student stu = new JavaStudent();
stu.project("");//父类对象无法调用子类中特有方法

//访问JavaStudent类中的特有方法
JavaStudent javaStu = (JavaStudent) stu;  //向下转型:把父类型转换为子类类型
javaStu.project("黑马考试系统");

小结

在使用多态时,存在着引用类型的转换:

  • 向上转型: 父引用指向子类对象时(子类类型自动转换为父类类型)

    • 弊端:父引用无法调用子类中的特有方法
  • 向下转型:把父类类型强制转换为子类类型

    • 书写格式: 子类 子类对象 = (子类) 父引用
07_多态:instanceof关键字

目标

  • 掌握instanceof关键字的使用

路径

  1. 向下转型时会发生的异常问题
  2. 使用关键字instanceof解决转型时的异常问题
  3. 案例:instanceof的应用

向下转型时出现的异常问题

异常:java.lang.ClassCastException

发生异常的原因:把子类类型转换为另一种子类类型时(类型不匹配)

使用关键字instanceof避免ClassCastException异常

书写格式:

if(对象名 instanceof 数据类型){
    //instanceof关键字的作用:判断指定的对象是否为某种类型
}
Student stu = new JavaStudent();

if( stu instanceof JavaStudent ) //检查stu对象底层是否为JavaStudent类型
{
    JavaStudent javaStu = (JavaStudent) stu;
    javaStu.setProject("黑马考试系统");
    
}else if( stu instanceof UiStudent ){
    UiStudent uiStu = (UiStudent) stu;
    uiStu.setOpus("茶具设计");
}    

案例:改造"考试系统"中的开始考试功能

public static void startExam(Student stu) {
        String subject = "";
        if (stu instanceof JavaStudent) {
            subject = "Java学科";
        } else if (stu instanceof UiStudent) {
            subject = "UI学科";
        }
        System.out.println("*****************" + subject + "考试题****************");
        stu.exam();
}

小结

instanceof关键字的作用:

  • 可以判断对象的类型

应用场景:

  • 可以根据不同的对象类型,来执行不同的功能
  • 可以避免多态中的向下转换时出现的ClassCaseException异常

二、权限和final关键字

08_关键字:权限修饰符

目标

  • 了解java中四种访问权限的特点

路径

  1. 访问权限修饰符

访问权限修饰符(关键字)

权限关键字:

  • public,公开的 【没有底限,可以任意访问】
  • private,私有的 【最小的访问范围:在本类中】
  • 默认的 (在代码上不书写任何关键字)
  • protected , 受保护的(专为子类提供的)

访问权限从小到大排序: private < 默认的 < protected < public

publicprotected默认的private
同一类中
同一包中的子类
同一包中的无关类(非子类)
不同包的子类
不同包中的无关类(非子类)

结论:public具有最大权限。private则是最小权限

​ 默认的访问范围只认同一个包下

​ protected访问范围只认子类(同一个包也可以)

建议:

  • 通常在开发中,如没有特殊需求,属性全部设置为private,方法都设置为public

小结

从大到小排列访问权限:public 、protected、默认的、private

09_关键字:final

目标

  • 掌握final修饰符的不同应用

路径

  1. final修饰符的介绍
  2. final修饰符的应用场景

final修饰符

final的含义:最终的、不可改变的

在java语言中,使用final可以用来修饰:类、变量、方法

格式:

//修饰类
public final class Student{
}

//修饰方法
public final void method(){
}

//修饰变量
private final String name="小明";

final在开发中的应用场景

  • 当定义常量时:

    • 变量添加final修饰符后,变量成为了常量

    • 常量的值只能赋值一次

    • final int number = 10;
      //后续无法再修改number的值
      number=100;//报错
      
  • 当类中的方法不能被子类重写时

    • 在方法是添加final修饰符(方法不能重写)

    • class Father{
          //不可以改变的方法(不能被子类重写)
          public final void method(){       
          }
      }
      //子类  继承父类
      class Son extends Father{
          //子类无法对Father类中的method进行重写
      }
      
  • 不希望类被继承时

    • 在类上添加final修饰符(类不能被继承)

    • final class Father{
          //类不能被继承
      }
      //报错:Father类不能被继承
      class Son extends Father{}
      

小结

  • final修饰符号,可以用来修饰:类、方法、变量
  • final修饰类,类不能被继承
  • final修饰方法,方法不能被重写
  • final修饰变量,变量成为了常量,初始化值之后无法修改常量的值

三、接口

10_接口:接口的定义

目标

  • 掌握接口的定义方式

路径

  1. 接口的介绍
  2. 接口的定义
  3. 接口中的成员

接口的介绍

接口,是java语言中的一种引用类型。 已经学习过的引用类型:数组、类、String、集合

接口,和类属于同一级别的

接口,可以理解为是方法的集合体(接口中通常就是用定义方法的)

  • 接口中封装的就是抽象方法(JDK1.7之前)
  • 从JDK1.8开始,接口中增加了:静态方法、默认方法
  • 从JDK1.9开始,接口中增加了:私有方法

接口,不能实例化(不能创建对象)【接口中没有构造方法】

接口的定义

定义类:

class HelloWorld{
    //成员变量
    //成员方法
    //构造方法
}

定义接口: 使用关键字interface

interface Hello{
    //接口中的成员
}

接口中的成员

JDK1.8之前的接口中只能定义两个成员:抽象方法、静态常量(在后面内容中介绍)

JDK1.8添加了:静态方法、默认方法

JDK1.9添加了:私有方法

//接口名的命名方式:大驼峰
public interface HelloInter{
    //静态常量
    public static final int NUMBER=100;  //常量名通常全大写
    
    //抽象方法
    public abstract void method();
}

//JDK1.8:
public interface HelloInter{
    //静态常量
    //抽象方法
    
    //默认方法
    public default int addNum(int n){
        return  n + 1;
    }
    //静态方法
    public static void method(){
        
    }
}

//JDK1.9
public interface HelloInter{
    //静态常量
    //抽象方法
    //默认方法
    //静态方法
    
    //新增:私有方法
    private boolean isOpen(){
        return false;
    }
}

小结

接口的定义方式:interface 接口名{ … }

接口中可以书写的内容:

  • 静态常量
  • 抽象方法
  • 静态方法
  • 默认方法
  • 私有方法
11_接口:接口的基本使用

目标

  • 能够使用implements关键字实现接口

路径

  1. 实现接口的书写方式
  2. 接口中的抽象方法

实现接口的格式

定义接口:

interface Hello{
    //常量
    public static final int NUMBER=100;
    //抽象方法
    public abstract void method(int num);
}

在java中接口不能实例化,需要定义一个子类来实现(继承)接口,通过实例化子类对象,来访问接口的成员

子类实现接口,使用关键字:implements

//子类  实现  接口
class Child implements Hello{
    //重写抽象方法
    public void method(int num){
        //方法体代码
    }
}

接口中的抽象方法

在子类实现接口之后,必须对接口中的抽象方法进行重写

class Child implements Hello{
    //重写抽象方法
    public void method(int num){
        //方法体代码
    }
}

//实例化子类对象
Child c = new Child(); //使用对象本身类型来定义
c.method(); //调用重写后的方法

//多态的体现
Hello h = new Child();//使用对象的父类型来定义
h.method(); //调用重写后的方法
//多态:
父类/父接口   父引用  =  new  子类();

List list = new ArrayList()

小结

定义接口使用:interface

public interface 接口名{
    //静态常量
    //抽象方法
}

实现接口使用:implements

public class 实现类 implements 接口{
    //重写接口中的所有的抽象方法
}

使用接口中的功能:

//实例化子类
子类 对象 = new 子类();

//多态:
接口 对象 = new 子类();
12_接口:接口的应用案例

目标

  • 使用接口改造"考试系统"中的登录功能

路径

  1. 分析案例中存在的问题
  2. 代码实现

分析案例中的问题

//父类
public abstract class Student {
    //省略成员变量
    //省略构造方法
    
    //登录
    public abstract boolean login(String name,String passwd);
    public abstract boolean login(int phoneCode);
    public abstract boolean login(String face);

    //省略getter()、setter()
}

//子类
public class JavaStudent extends Student{
    //登录:用户名和密码
    @Override
    public boolean login(String name,String passwd){
        Scanner sc = new Scanner(System.in);
        System.out.print("用户名:");
        String loginName = sc.next();
        System.out.print("密码:");
        String loginPwd =sc.next();
        return true;
    }
    
     //登录:手机验证码
    @Override
    public boolean login(int phoneCode){
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入手机验证码:");
        int pc = sc.nextInt();
        return true;
    }

    //登录:人脸识别
    @Override
    public boolean login(String face){
        System.out.print("请不要动,人脸识别中...");
        return true;
    }
}

思考:当程序中再增加一种新的登录方式"微信登录",程序代码怎么修改?

//修改父类代码
public abstract Student{
    //登录
    public abstract boolean login(String name,String passwd);
    public abstract boolean login(int phoneCode);
    public abstract boolean login(String face);
    
    //新增:
    public abstract boolean login(WeiXin weixin)
}

//修改子类代码
public class JavaStudent extends Student{
    //登录1:用户名、密码
    //登录2:手机验证码
    //登录3:人脸识别
    
    //新增登录4: 微信登录
    public boolean login(WeiXin weixin){
        //........
    }
}

分析出的问题:

1、随着新的登录功能的添加,父类和子类中的代码会越来越多

2、企业中开发的思想:尽量避免修改原有类中的代码

3、现有案例"黑马考试系统"中,程序代码的复用性并不强、扩展性不强

解决方案:使用接口改造代码

接口作用:

1、用来定义标准

代码实现

//定义接口:登录适配器接口
public interface ILoginAdapter {
    public boolean login();
}

//账号登录
public class AccoutLogin implements ILoginAdapter {
    @Override
    public boolean login() {
        return account();
    }

    public boolean account(){
        Scanner sc = new Scanner(System.in);
        System.out.print("用户名:");
        String loginName = sc.next();
        System.out.print("密码:");
        String loginPwd =sc.next();
        return true;
    }
}

//父类:Student
public abstract class Student {
    private String number;//学号
    private String name;//姓名
    private int age;//年龄
    private String classes;//班级

    public Student() {
    }
    public Student(String number, String name, int age, String classes) {
        this.number = number;
        this.name = name;
        this.age = age;
        this.classes = classes;
    }

    //考试
    public abstract void exam();
    
    /**
     * 登录
     * @param loginAdapter  登录适配器接口  作为形参
     * @return  登录结果
     */
    public abstract boolean login(ILoginAdapter loginAdapter);

    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getClasses() {
        return classes;
    }
    public void setClasses(String classes) {
        this.classes = classes;
    }
}

//子类:JavaStudent
public class JavaStudent extends Student{
    public JavaStudent() {
    }
    public JavaStudent(String number, String name, int age, String classes) {
        super(number, name, age, classes);
    }

    /**
     * 考试
     */
    @Override
    public void exam() {
       System.out.println("Java学生,进行阶段性考试!");
    }
    
    /**
     * 登录
     */
    @Override
    public boolean login(ILoginAdapter loginAdapter) {
        //多态的体现:根据传递的不同对象,调用不同的登录
        return loginAdapter.login();
    }
}

//考试系统
public class ExamSys {
    public static void main(String[] args) {
        init();
    }

    public static void init() {
        System.out.println("******************黑马考试系统******************");
        System.out.println("请选择学科: 1) Java \t 2) UI");
        int subjectNumber = new Scanner(System.in).nextInt();
        switch (subjectNumber) {
            case 1:
                JavaStudent javaStu = new JavaStudent();
                //考试前:先登录
                if (login(javaStu)) {
                    System.out.println("登录成功!");
                    startExam(javaStu);
                }
                break;
            case 2:
                UiStudent uiStu = new UiStudent();
                if (login(uiStu)) {
                    startExam(uiStu);
                }
                break;
            default:
                System.out.println("选择错误,退出系统!");
                System.exit(0);
        }
    }

    //登录
    public static boolean login(Student stu) {
        System.out.println("---------------------------------------------");
        System.out.println("请选择登录方式:");
        System.out.println("1、用户名/密码");
        System.out.println("2、手机验证码");
        System.out.println("3、人脸识别");
        int loginNumber = new Scanner(System.in).nextInt();
        System.out.println("---------------------------------------------");
        boolean result = false;
        switch (loginNumber) {
            case 1:
                //多态的体现:子类对象作为实参
                result = stu.login( new AccoutLogin() );
                break;
            case 2:
                result = stu.login(new ValidateCodeLogin());
                break;
            case 3:
                //
                break;
        }
        return result;
    }

    //开始考试
    public static void startExam(Student stu) {
        String subject = "";
        if (stu instanceof JavaStudent) {
            subject = "Java学科";
        } else if (stu instanceof UiStudent) {
            subject = "UI学科";
        }
        System.out.println("*****************" + subject + "考试题****************");
        stu.exam();
    }
}
13_接口:接口的多实现和多继承

目标

  • 掌握接口的多实现和多继承的书写

路径

  1. 接口多实现的书写方式
  2. 接口多继承的书写格式
  3. 继承类的同时接口多实现格式

接口的多实现

类和类之间是什么关系?

  • 继承关系

类和接口之间是什么关系?

  • 实现关系

一个类可以继承多个父类吗?

  • 不可以。 类只能单一继承

一个类可以实现多个接口吗?

  • 可以

接口作用:

  • 解决类只能单一继承的问题(接口的多实现)

类实现多个接口的格式:

interface InterA{
    public abstract void method1();
}
interface InterB{
    public abstract void method2();
}
interface InterC{
    public abstract void method3();
}

//子类实现多个接口     多个接口之间使用逗号分隔
class Child implements InterA,InterB,InterC{
    //子类中需要把所接口中的抽象方法全部重写
}

疑问:如果多个接口中存在相同的抽象方法时,子类实现接口时怎么办?

答案:针对相同的抽象方法,子类只需要重写1次

interface InterA{
    public abstract void method();
}
interface InterB{
    public abstract void method();
}
interface InterC{
    public abstract void method();
}
//子类
class Child implements InterA,InterB,InterC{
    //父接口中相同的抽象方法,子类只需要重写一次
    public void method(){
        
    }
}

接口的多继承

类和类之间是:继承

类和接口之间是:实现

接口和接口之间是:继承

interface InterA{
    public abstract void method();
}
interface InterB{
    public abstract void show();
}

//子接口  接口之间允许多继承
interface MyInter extends InterA,InterB{
    //当前的子接口中具有:method、show两个抽象方法
}

class Child implements MyInter{
    //重写:method、show方法
}

继承父类的同时进行接口的多实现

class Child extends 父类 implements 接口1,接口2,接口3{
    //重写所有接口中的抽象方法
    //假设父类为抽象类时,重写抽象类中的抽象方法
}

小结

接口的多实现:

public class 子类 implements 接口1,接口2,接口3,.......{
    
}

接口的多继承:

public interface 子接口 extends 接口1,接口2,....{
    
}

子类继承父类的同时,也实现接口:

public 子类 extends 父类 implements 接口1,接口2,...{
    
}
14_接口:接口和抽象类的区别

目标

  • 了解接口和抽象类在应用上的区别

路径

  1. 接口和抽象类的区别

接口和抽象的区别

抽象类:

  • 用来封装事物的属性、行为
  • 抽象类中有:成员变量、成员方法(静态方法、私有方法)、构造方法、抽象方法
  • 抽象类不能实例化,是由子类实例化后使用的
  • 子类只能继承一个抽象类(单一继承)
  • 抽象类通常是描述一个事物

接口:

  • 用来封装行为
  • 接口中有:静态常量、抽象方法、静态方法、默认方法、私有方法
  • 接口不能实例化,是由子类实例化后使用
  • 子类可以实现多个接口(多实现)
  • 接口通常是用来制定标准 (后面学习的课程中还会遇到很多。例:JDBC)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值