3接口&多态

JavaSE进阶-day03

一、接口

1.黑马信息管理系统-集合改进【】(视频01) (10‘’)
  • 使用数组容器的弊端

1.容器长度是固定的,不能根据添加功能自动增长

2.没有提供用于赠删改查的方法

  • 优化步骤

    1.创建新的StudentDao类,OtherStudentDao

    2.创建ArrayList集合容器对象

    3.OtherStudentDao中的方法声明,需要跟StudentDao保持一致

    ​ 注意:如果不一致,StudentService中的代码就需要进行修改。

    4.完善方法(添加、删除、修改、查看)

    5.替换StudentService中的Dao对象

  • 集合转换成数组的方法

    Student[] students = new Student[stus.size()];
    stus.toArray(students);
    
  • 代码流程图

在这里插入图片描述

  • OtherStudentDao类

    /**
     * 开闭原则: 对扩展开放、对修改关闭
     *
     *
     * 低耦合
     */
    public class OtherStudentDao {
        // 集合容器
        private static ArrayList<Student> stus = new ArrayList<>();
    
        static {
            Student stu1 = new Student("heima001","张三","23","1999-11-11");
            Student stu2 = new Student("heima002","李四","24","2000-11-11");
    
            stus.add(stu1);
            stus.add(stu2);
        }
    
        // 添加学生方法
        public boolean addStudent(Student stu) {
           stus.add(stu);
           return true;
        }
    
        // 查看学生方法
        public Student[] findAllStudent() {
            Student[] students = new Student[stus.size()];
            stus.toArray(students);
            return students;
        }
    
        public void deleteStudentById(String delId) {
            // 1. 查找id在容器中所在的索引位置
            int index = getIndex(delId);
            stus.remove(index);
        }
    
        public int getIndex(String id){
            int index = -1;
            for (int i = 0; i < stus.size(); i++) {
                Student stu = stus.get(i);
                if(stu != null && stu.getId().equals(id)){
                    index = i;
                    break;
                }
            }
            return index;
        }
    
        public void updateStudent(String updateId, Student newStu) {
            // 1. 查找updateId, 在容器中的索引位置
            int index = getIndex(updateId);
            stus.set(index, newStu);
        }
    }
    
2.黑马信息管理系统-抽取公共Dao【】(视频02) (6‘’)
  • 抽取公共Dao

    public abstract class BaseStudentDao {
        // 添加学生方法
        public abstract boolean addStudent(Student stu);
        // 查看学生方法
        public abstract Student[] findAllStudent();
        // 删除学生方法
        public abstract void deleteStudentById(String delId);
        // 根据id找索引方法
        public abstract int getIndex(String id);
        // 修改学生方法
        public abstract void updateStudent(String updateId, Student newStu);
    }
    
  • 实现继承

    public class StudentDao extends BaseStudentDao {}
    
    //快捷键 alt + insert  :  快速进行方法重写
    public class OtherStudentDao extends BaseStudentDao {}
    
3.接口介绍【】(视频03) (5‘’)
  1. 什么是接口

    接口就是一种公共的规范标准,只要符合规范标准,都可以使用

    当一个类中的所有方法都是抽象方法的时候,我们就可以将其定义为接口

  2. 接口存在的意义

    规则的定义

    程序的扩展

4.接口的定义和特点【重点】(视频04) (9‘’)
  1. 如何定义接口

    //public interface 接口名{}
    public interface Inter {
        public abstract void study();
    }
    
  2. 如何实现接口

    //public class 类名 implements 接口名{}
    public class InterImpl implements Inter {
        @Override
        public void study() {
            System.out.println("我是实现类中的study方法");
        }
    }
    
  3. 当一个类中的所有方法都是抽象方法的时候,我们就可以将其定义为接口, 为什么?

    1、接口(干爹)不占用继承(亲爹)的位置

    2、使用接口需要写的代码量少

在这里插入图片描述

  1. 接口的特点

    • 接口不能被实例化

    • 接口的实现类 : 如果实例类不是抽象类,就必须重写接口中所有的抽象方法

    • 接口和实现类关系,可以单实现,也可以多实现

    //接口
    public interface Inter {
     public abstract void study();
    }
    
    //接口
    public interface InterA {
        public abstract void print1();
        public abstract void print2();
        public abstract void study();
    }
    
    //实现类 - 必须实现接口中所有的抽象方法
    class InterImpl implements Inter{
     public void study(){}
    }
    
    //可以单实现,也可以多实现
    public class InterImpl implements Inter , InterA {
        @Override
        public void study() {
            System.out.println("我是实现类中的study方法");
        }
    
        @Override
        public void print1() {
        }
    
        @Override
        public void print2() {
        }
    }
    
自由练习-5分钟 - (接口的定义)
5.接口中的成员特点【重点】(视频05) (8‘’)
  • 成员变量

    只能是常量,默认修饰符为:public static final

    public interface Inter {
        public static final int NUM = 10;
    }
    
    public class TestInterface {
        /*
            成员变量: 只能是常量 系统会默认加入三个关键字
                        public static final
         */
        public static void main(String[] args) {
            System.out.println(Inter.NUM);
        }
    }
    
    class InterImpl implements Inter{
    
        public void method(){
            // NUM = 20;
            System.out.println(NUM);
        }
    
    }
    
  • 构造方法

    接口中没有构造方法

    public interface Inter {
        public static final int NUM = 10;
    	
        // 接口中 - 构造方法: 不存在
        // public Inter(){}
    
        public abstract void show();
    }
    
    
    class InterImpl extends Object implements Inter{
    		
        //接口实现类中,  super() 调用的是父类的构造方法(比如: Object)
        public InterImpl(){
            super();
        }
        
    }
    
  • 成员方法

    只能是抽象方法,默认修饰符为:public abstract
    注意:jdk8版本以前

    public interface Inter {
      /*
    成员方法: 只能是抽象方法, 系统会默认加入两个关键字 
                             public abstract
    
         JDK8以后可以有静态方法
         JDK9以后可以有默认方法
      */
       public abstract void show();
    }
    
6.JDK8版本中接口成员的特点-默认方法【了解】(视频06) (8‘’)
  • 默认方法的作用

    解决接口升级的问题

在这里插入图片描述

  • 默认方法的格式

    //格式:public default 返回值类型 方法名(参数列表) {}
    //注意: 默认方法只能使用 public进行修饰
    public default void show3() {   
    }
    
  • 默认方法的注意事项

  • 默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字
  • 如果实现了多个接口,多个接口中存在相同的方法声明,实现类就必须对该方法进行重写
  • public可以省略,default不能省略
7.JDK8版本中接口成员的特点-静态方法 【了解】(视频07) (5‘’)
  • 静态方法 - 语法格式

    //格式:public static 返回值类型 方法名(参数列表) { }
    public static void show() {
    }
    
  • 接口中静态方法的注意事项

    • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
    • public可以省略,static不能省略
    public interface InterA {
    
        public static void show() {
        }
    
    }
    
    class InterAImpl implements InterA {
    
    }
    
    class Test {
        public static void main(String[] args) {
            InterA.show();   //可以
    
            InterAImpl.show();  //不可以
    
            InterAImpl interA = new InterAImpl();
            interA.show();  //不可以
        }
    }
    
8.JDK9版本中接口成员的特点-私有方法 【了解】(视频08) (8‘’)
  • 私有方法 - 使用格式

    //格式1:private 返回值类型 方法名(参数列表) {   }
    private void show() {  }
    
    //格式2:private static 返回值类型 方法名(参数列表) {  }
    private static void method() {  }
    
  • 接口中私有方法的注意事项

    • 私有方法是jdk9才存在的, jdk9以前接口中方法的访问权限只能是公共的
    • 静态方法只能调用静态的私有方法,不能调用普通的私有方法
9.类和接口的关系【】(视频09) (8‘’)
  1. 类和接口的关系

    • 类和类之间的关系

      继承关系 : 可以单继承,不能多继承,但是可以多层继承

      组合关系: A类中存在B类的成员变量

    • 类和接口之间的关系

      实现关系,可以单实现,也可以多实现
      还可以继承一个类的同时,再实现多个接口

      class InterImpl extends Object implements Inter{
      		
          //接口实现类中,  super() 调用的是父类的构造方法(比如: Object)
          public InterImpl(){
              super();
          }
          
      }
      
    • 接口和接口之间的关系

      继承关系,可以单继承、也可以多继承

      public interface InterC extends InterA , InterB {
      	
      }
      
    • 为什么类只能单继承 而类却可以实现多接口? 为什么接口可以多继承接口?

在这里插入图片描述

 ```java
 //为什么类却可以实现多接口?
 public interface Inter {
     public abstract void study();
 }
 
 interface InterA {
     public abstract void study();
 }
 
 class InterImpl implements Inter, InterA {
 
     @Override
     public void study() {
 
     }
 }
 ```

 ```java
 //为什么接口可以多继承接口?
 public interface InterA {
     public abstract void study();
 }
 
 interface InterB {
     public abstract void study();
 }
 
 interface InterC extends InterA, InterB {
     public abstract void study();
 }
 
 
 class D implements InterC {
     @Override
     public void study() {
 
     }
 }
 ```

 结论: 类多继承会造成逻辑冲突, 类实现多接口不会逻辑冲突,接口继承多接口也不会逻辑冲突
10.黑马信息管理系统-接口改进【】(视频10) (2‘’)
  • BaseStudentDao类改为接口

    public interface BaseStudentDao {
        // 添加学生方法
        boolean addStudent(Student stu);
    
        // 查看学生方法
        Student[] findAllStudent();
    
        // 删除学生方法
        void deleteStudentById(String delId);
    
        // 根据id找索引方法
        int getIndex(String id);
    
        // 修改学生方法
        void updateStudent(String updateId, Student newStu);
    }
    
  • 实现接口

    public class StudentDao implements BaseStudentDao {}
    
    public class OtherStudentDao implements BaseStudentDao {}
    

二、多态

1.黑马信息管理系统-多态引入【】(视频11) (6‘’)
  • 存在问题- service与dao耦合性大

    public class StudentService {
        private StudentDao studentDao = new StudentDao();
    }
    
    public class StudentService {
        private OtherStudentDao studentDao = new OtherStudentDao();
    }
    
  • 解决方案,创建工厂

    public class StudentDaoFactory {
        public static OtherStudentDao getStudentDao(){
           return new OtherStudentDao();
        }
    }
    
    public class StudentService {
        // 通过学生库管工厂类, 获取库管对象
        private OtherStudentDao studentDao = StudentDaoFactory.getStudentDao();
    }
    
2.多态的前提条件【重点】(视频12) (6‘’)
  1. 什么是多态?

    同一个对象,在不同时刻表现出来的不同形态 ( h2O 水 冰 气)

    public class Test1Polymorphic {
    	
        //同一个对象 new Cat(); 可以使用不同类型的变量引用
        public static void main(String[] args) {
            // 当前事物, 是一只猫
            Cat c = new Cat();
            
            // 当前事物, 是一只动物
            Animal a = new Cat();
            a.eat();
        }
    }
    
    class Animal {
        public void eat(){
            System.out.println("动物吃饭");
        }
    }
    
    class Cat extends Animal {
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
  2. 多态的前提条件有哪些?

    要有继承/实现关系
    要有方法重写
    要有父类引用指向子类对象

    //前提条件之 - 实现关系
    public interface Animal {
    }
    
    //前提条件之 - 实现关系
    public class Cat implements Animal {
    
        @Override
        public void eat() {
        }
    
        public static void main(String[] args) {
            Animal a = new Cat();
        }
    }
    
自由练习-6分钟 - (什么是多态)
3.多态中成员访问的特点 【重点】(视频13) (7‘’)
  • 成员变量

    编译看左边(父类)、运行看左边(父类)

    public class Test2Polymorpic {
        /*
             多态的成员访问特点:
                成员变量: 编译看左边 (父类), 运行看左边 (父类)
                
                编译看左边 (父类): 当父类不存在num变量时,代码编译就会报错
                运行看左边 (父类): 运行结果,10
                    
         */
        public static void main(String[] args) {
            Fu f = new Zi();
            System.out.println(f.num);
        }
    }
    
    class Fu {
        int num = 10;
    }
    
    class Zi extends Fu {
        int num = 20;
    }
    
  • 成员方法

    编译看左边(父类)、运行看右边(子类)

    前提:进行了方法重写
    静态方法本质上是没有进行重写的,编译运行都是左边
    final修饰的方法不能进行重写,编译运行都是左边
      public class Test2Polymorpic {
          /*
               多态的成员访问特点:
      			 成员方法: 编译看左边 (父类), 运行看右边 (子类)
      			 
      		     编译看左边 (父类):  父类中不存在method方法,编译就会报错
      		     运行看右边 (子类): 子类重写了父类方法,运行结果: 执行子类method方法
           */
          public static void main(String[] args) {
              Fu f = new Zi();
              f.method();
          }
      }
      
      class Fu {
          public void method(){
              System.out.println("Fu.. method");
          }
      }
      
      class Zi extends Fu {
          public void method(){
              System.out.println("Zi.. method");
          }
      }
    
4.多态的好处和弊端 【】(视频14) (9‘’)
  • 多态的好处

    提高了代码的扩展性
    定义方法时,如果将父类型作为参数,在使用方法时,可以传递任意子类对象 (重点)

    代码图:
    在这里插入图片描述

    代码实现:

    public class Test3Polymorpic {
        public static void main(String[] args) {
            useAnimal(new Dog());
            useAnimal(new Cat());
        }
    
        public static void useAnimal(Animal a){  
            a.eat();
        }
        
    }
    
    abstract class Animal {
        public abstract void eat();
    }
    
    class Dog extends Animal {
        public void eat() {
            System.out.println("狗吃肉");
        }
    }
    
    class Cat extends Animal {
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
    
  • 多态的弊端

    不能使用子类特有的成员

自由练习-10分钟
5.多态中的转型 【重点】(视频15) (6‘’)
  • 多态中的向上转型

    父类引用指向子类对象其实就是向上转型。例如:
    Animal a = new Dog();

    public class Test1Polymorphic {
    	
        //同一个对象 new Cat(); 可以使用不同类型的变量 作为返回值
        public static void main(String[] args) {
            Cat c = new Cat();
            Animal a = new Cat();  //向上转型
            a.eat();
        }
    }
    
    class Animal {
        public void eat(){
            System.out.println("动物吃饭");
        }
    }
    
    class Cat extends Animal {
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
  • 多态中的向下转型

    将父类型的引用转换成具体的子类对象。转换格式:
    子类 对象名 = (子类)父类引用;

    public class Test3Polymorpic {
        public static void main(String[] args) {
            useAnimal(new Dog());
            useAnimal(new Cat());
        }
    
        public static void useAnimal(Animal a){
            Dog dog = (Dog) a;  //向下转型  
            dog.watchHome();
        }
    
    }
    
    abstract class Animal {
        public abstract void eat();
    }
    
    class Dog extends Animal {
        public void eat() {
            System.out.println("狗吃肉");
        }
    
        public void watchHome(){
            System.out.println("看家");
        }
    }
    
    class Cat extends Animal {
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
6.多态中转型存在的风险和解决方案 【重点】(视频16) (6‘’)
  • 多态中转型存在的风险

    代码运行的过程中可能会出现 ClassCastException 类型转换异常

  • 多态中转型风险的解决方案

    如何避免强转可能会出现的问题
    关键字 instanceof
    使用格式:
    变量名 instanceof 类型
    通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果

    public class Test3Polymorpic {
        public static void main(String[] args) {
            useAnimal(new Dog());
            useAnimal(new Cat());
        }
    
        public static void useAnimal(Animal a){    		
             //存在风险   ClassCastException  类型转换异常
     	     //Dog dog = (Dog) a;
             //dog.watchHome();
           
            //解决方案  判断a变量记录的类型, 是否是Dog
            if(a instanceof Dog){
                Dog dog = (Dog) a;
                dog.watchHome();
            }
    
        }
    }
    
    abstract class Animal {
        public abstract void eat();
    }
    
    class Dog extends Animal {
        public void eat() {
            System.out.println("狗吃肉");
        }
    
        public void watchHome(){
            System.out.println("看家");
        }
    }
    
    class Cat extends Animal {
        public void eat() {
            System.out.println("猫吃鱼");
        }
    }
    
自由练习-5分钟
7.黑马信息管理系统-多态改进 【】(视频17) (6‘’)
  • 工厂类,以多态的形式返回对象

    public class StudentDaoFactory {
        public static BaseStudentDao getStudentDao(){
            return new OtherStudentDao();
        }
    }
    
  • StudentService类

    public class StudentService {
        // 通过学生库管工厂类, 获取库管对象
    	private BaseStudentDao studentDao = StudentDaoFactory.getStudentDao();
    }
    
  • 代码图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

InLoadwetrust

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

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

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

打赏作者

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

抵扣说明:

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

余额充值