多态

image.png

image.png
image.png

  1. package com.lagou.task09;
  2. /**
  3. * @author 西风月
  4. * @date 2020/7/14
  5. * @description
  6. */
  7. public class Shape {
  8. private int x;
  9. private int y;
  10. public Shape() {
  11. }
  12. public Shape(int x, int y) {
  13. setX(x);
  14. setY(y);
  15. }
  16. public int getX() {
  17. return x;
  18. }
  19. public void setX(int x) {
  20. this.x = x;
  21. }
  22. public int getY() {
  23. return y;
  24. }
  25. public void setY(int y) {
  26. this.y = y;
  27. }
  28. public void show() {
  29. System.out.println("横坐标 :" + getX() + ", 纵坐标 :" + getY());
  30. }
  31. }
  1. package com.lagou.task09;
  2. /**
  3. * @author 西风月
  4. * @date 2020/7/14
  5. * @description
  6. */
  7. public class Rect extends Shape {
  8. private int len;
  9. private int wid;
  10. public Rect() {
  11. }
  12. public Rect(int x, int y, int len, int wid) {
  13. super(x, y);
  14. setLen(len);
  15. setWid(wid);
  16. }
  17. public int getLen() {
  18. return len;
  19. }
  20. public void setLen(int len) {
  21. if(len > 0)
  22. this.len = len;
  23. else
  24. System.out.println("长度不合理!");
  25. }
  26. public int getWid() {
  27. return wid;
  28. }
  29. public void setWid(int wid) {
  30. if(wid > 0)
  31. this.wid = wid;
  32. else
  33. System.out.println("宽度不合理哦!");
  34. }
  35. @Override
  36. public void show() {
  37. super.show();
  38. System.out.println("长度是:" + getLen());
  39. System.out.println("宽度是:" + getWid());
  40. }
  41. }
  1. package com.lagou.task09;
  2. /**
  3. * @author 西风月
  4. * @date 2020/7/14
  5. * @description
  6. */
  7. public class ShapeRectTest {
  8. public static void main(String[] args) {
  9. Shape s1 = new Shape(17,2);
  10. //当Rect类中没有重写show方法时,调用父类的show方法
  11. //当Rect类重写show方法后,下面调用Shape类中show方法
  12. s1.show();
  13. System.out.println("=============================");
  14. Rect r1 = new Rect(3,4,5,6);
  15. //当Rect类中没有重写show方法时,调用父类的show方法
  16. //当Rect类重写show方法后,下面调用Rect类中show方法
  17. r1.show();
  18. System.out.println("=============================");
  19. Shape s2 = new Rect(8,8,9,9);
  20. //当Rect类中没有重写show方法时,调用父类的show方法
  21. //当Rect类重写show方法后,下面的代码在编译阶段调用Shape中的show方法, 在运行阶段调用Rect类中show方法
  22. s2.show();
  23. }
  24. }

image.png

  1. package com.lagou.task09;
  2. /**
  3. * @author 西风月
  4. * @date 2020/7/14
  5. * @description
  6. */
  7. public class ShapeRectTest {
  8. public static void main(String[] args) {
  9. Shape s1 = new Shape(17,2);
  10. //当Rect类中没有重写show方法时,调用父类的show方法
  11. //当Rect类重写show方法后,下面调用Shape类中show方法
  12. s1.show();
  13. System.out.println("=============================");
  14. Rect r1 = new Rect(3,4,5,6);
  15. //当Rect类中没有重写show方法时,调用父类的show方法
  16. //当Rect类重写show方法后,下面调用Rect类中show方法
  17. r1.show();
  18. System.out.println("=============================");
  19. Shape s2 = new Rect(8,8,9,9);
  20. //当Rect类中没有重写show方法时,调用父类的show方法
  21. //当Rect类重写show方法后,下面的代码在编译阶段调用Shape中的show方法, 在运行阶段调用Rect类中show方法
  22. s2.show();
  23. System.out.println("=============================");
  24. //测试Shape类型的引用能否直接调用父类和子类独有的方法??
  25. System.out.println("获取到的横坐标:" + s2.getX());
  26. //s2.getLen(); Err:Shape类中找不到Rect中独有的方法
  27. s2.show();
  28. //调用静态方法
  29. System.out.println("=============================");
  30. s2.test(); //提示不建议使用引用.的方式访问
  31. Shape.test(); //推荐使用
  32. }
  33. }

使用父类类型的引用调用子类独有方法的方式

image.png

子类 is-a 父类

  • 子类转父类是小类型到大类型
    • 自动类型转换 , 向上转型
  • 父类转子类是大类型到小类型
    • 强制类型转换, 显式类型的转换,. 向下转型

image.png

  • 几个异常:
    • ArithmeticException 异常 算术异常
    • NumberFormatException: 数字格式异常
    • ArrayIndexOutOfBoundsException: 数组下标越界异常
    • NullPointerException: 空指针异常
    • classCastException - 类型转换异常

image.png

抽象

抽象方法

image.png

抽象类

image.png
如果一个抽象类中没有抽象方法,抽象类中不能new对象原因是抽象类中包含抽象方法。不包含抽象方法的抽象类不是真正意义上的抽象类。

  1. package com.lagou.task09;
  2. /**
  3. * @author 西风月
  4. * @date 2020/7/15
  5. * @description
  6. */
  7. public abstract class AbstractTest {
  8. private int cnt;
  9. public AbstractTest() {
  10. }
  11. public AbstractTest(int cnt) {
  12. setCnt(cnt);
  13. }
  14. public int getCnt() {
  15. return cnt;
  16. }
  17. public void setCnt(int cnt) {
  18. this.cnt = cnt;
  19. }
  20. public abstract void show() ;
  21. public static void main(String[] args) {
  22. // AbstractTest at = new AbstractTest(); //抽象类不能实例化对象
  23. // System.out.println("at.cnt=" + at.getCnt());
  24. }
  25. }

image.png

  • 模板设计模式

image.png

  • 多态的优点:

为了屏蔽不同子类的差异性,实现通用得编程

  • 多态的**缺点: **
    • 父类类型的引用不能直接访问子类独有的方法, 若调用则需要强转。

image.png

抽象类的应用

image.png

  • 抽象方法不能为private
  • 抽象方法不能为static
  • 抽象方法不能为 final ```java package com.lagou.task09;

/**

  • @author 西风月
  • @date 2020/7/15
  • @description */ public abstract class AbstractAccount { //public final abstract class AbstractAccount { Err private double money; //Define abstract method public abstract double getLixi(); // public static abstract double getLixi(); Err // public final abstract double getLixi(); Error // private abstract double getLixi(); Error

    public AbstractAccount() { }

    public AbstractAccount(double money) {

    1. this.money = money;

    }

    public double getMoney() {

     return money;
    

    }

    public void setMoney(double money) {

     this.money = money;
    

    } } ```

package com.lagou.task09;

/**
 * @author 西风月
 * @date 2020/7/15
 * @description
 */
public class FixedAccount extends AbstractAccount {

    public FixedAccount(int i) {
        super(i);
    }

    @Override
    public double getLixi() {
        return getMoney() * 0.03 * 1;
    }

    public static void main(String[] args) {
        AbstractAccount aat = new FixedAccount(1000);
        System.out.println("计算所得利息是:" + aat.getLixi());
    }
}

接口

image.png

image.png
image.png

  • 新特性 :从jdk1.9开始允许接口中出现私有方法
  • 里面只能有常量
    • public static final
  • 里面只能有抽象方法(新特性除外), 注释中的关键字可以省略,但建议写上 ```java package com.lagou.task09;

/**

  • @author 西风月
  • @date 2020/7/15
  • @description / public interface InterfaceTest { /public static final/ int CNT = 1; //里面只能有常量 //private void show() {}; //从jdk1.9开始允许接口中出现私有方法 /public abstract*/ void show(); //里面只能有抽象方法(新特性除外), 注释中的关键字可以省略,但建议写上 } ```

接口的实际意义:

  • 实现多继承 ```java package com.lagou.task09;

/**

  • @author 西风月
  • @date 2020/7/15
  • @description */

//使用implement关键字表达实现的关系,支持多实现 public class Gold implements Metal, Money { @Override public void shine() { System.out.println(“发出的金黄色的光芒!”); }

@Override
public void buy() {
    System.out.println("买了好多好吃的~");
}

public static void main(String[] args) {
    Metal mt = new Gold();
    mt.shine();

// if(mt instanceof Gold) // ((Gold) mt).buy();

    Money mn = new Gold();
    mn.buy();

   /* Money mn2 = new Money() {
        @Override
        public void buy() {
            System.out.println("================");
        }
    };
    mn2.buy();*/
}

}

```java
package com.lagou.task09;

/**
 * @author 西风月
 * @date 2020/7/15
 * @description
 */
public interface Metal {
    //自定义抽象方法描述发光的行为 
    public abstract void shine();
}
package com.lagou.task09;

/**
 * @author 西风月
 * @date 2020/7/15
 * @description
 */
public interface Money {
    public abstract void buy();
}

image.png
image.png

package com.lagou.task09;

/**
 * @author 西风月
 * @date 2020/7/15
 * @description
 */
public interface Runner {
    public abstract void run();
}
package com.lagou.task09;

/**
 * @author 西风月
 * @date 2020/7/15
 * @description
 */
public interface Hunter extends Runner {
    public abstract void hunt();
    //增加一个抽象方法
    //public abstract void show();

    //将两个默认方法中的重复代码打包以供复用
    private void show() {
        System.out.println("在以后的开发中,尽量减少重复代码,也就是减少代码冗余!");
    }

    public default void show1() {
        show();
        System.out.println("show1()方法:这里仅仅时接口中的一个默认功能,子类可以按需选择是否重写");
    }

    public default void show2() {
        show();
        System.out.println("show2()方法:这里仅仅时接口中的一个默认功能,子类可以按需选择是否重写");
    }

    //增加静态方法 隶属于类层级, 也就是接口层级
    public static void test() {
        System.out.println("这里时静态方法,可以直接通过接口名.的方式访问,省略对象的创建");
    }

}
package com.lagou.task09;

/**
 * @author 西风月
 * @date 2020/7/15
 * @description
 */
public class Man implements Hunter {
    @Override
    public void hunt() {
        System.out.println("出去打猎啦!");
    }

    @Override
    public void run() {
        System.out.println("我在追赶猎物!");
    }

    @Override
    public void show1() {
        System.out.println("为了给你几分薄面,就重写一下方法吧!");
    }

    public static void main(String[] args) {
        Runner r1 = new Man();
        r1.run();

        Hunter h1 = new Man();
        h1.hunt();
        h1.run();
        h1.show1();
        Hunter.test();
        //h1.test();  静态接口方法调用非法
        //应将接收方表达式替换为类型限定符 'com.lagou.task09.Hunter'
    }
}

抽象类以及接口的区别

  • abstract class / interface
  • extends/implements
  • 继承抽象类限制单继承, 接口可以多实现
  • 抽象类中可以有构造方法,接口中不可以有构造
  • 接口中类变量只能是常量,不能有成员变量
  • 抽象类中可以有成员方法,接口中只能由抽象方法
  • 抽象类增加方法子类可以不用重写,而接口中增加方法时实现需要重写(Java8以前的版本)

image.png
image.png

任务总结

  1. 多态(重中之重)
    1. 基本概念
    2. 语法格式:父类类型的引用指向子类的对象
    3. 多态的特点
      1. image.png
    4. 类型转换
      1. 父子类? -> instanceof
      2. 向上转型
    5. 实际意义
      1. 屏蔽不同子类的差异性实现,通用的编程带来最终不同的效果。
  2. 抽象类(重点)
    1. 抽象方法
      1. abstract 没有方法体
    2. 抽象类
      1. 抽象类不能实例化对象
    3. 抽象类跟抽象方法的关系
      1. 真正意义上的抽象类需要有abstract关键字+abstract方法
      2. super() 调用抽象类的构造方法
    4. 实际意义: 继承, 强制性,规范 模板设计模式
      1. 建议使用抽象类的引用指向子类对象, 实现多态
  3. 接口

基本概念: interface implements
常量
抽象方法 (Java8以前)
多实现
接口跟类之间的关系
抽象类和接口的主要区别
Java8、java9: 允许出现非静态方法
增加私有方法 private