zoukankan      html  css  js  c++  java
  • 9_多态

    多态的概念

    Rect类重写show方法的使用

    Shape.java

    Shape.java

    package cn.itcast.day01.demo13;
    
    public class Shape {
        private int x;
        private int y;
    
        public Shape() {}
    
        public Shape(int x, int y) {
            setX(x);
            setY(y);
        }
    
        public int getX() {
            return x;
        }
    
        public void setX(int x) {
            this.x = x;
        }
    
        public int getY() {
            return y;
        }
    
        public void setY(int y) {
            this.y = y;
        }
    
        public void show() {
            System.out.println("横坐标:" + x + ",纵坐标:" + y);
        }
    }
    

    Rect.java

    package cn.itcast.day01.demo13;
    
    public class Rect extends Shape{
        int len;
        int wid;
    
        public Rect() {}
    
        public Rect(int x, int y, int len, int wid) {
            super(x, y);
            setLen(len);
            setWid(wid);
        }
    
        public int getLen() {
            return len;
        }
    
        public void setLen(int len) {
            this.len = len;
        }
    
        public int getWid() {
            return wid;
        }
    
        public void setWid(int wid) {
            this.wid = wid;
        }
    
        @Override
        public void show() {
            super.show();
            System.out.println("长度是:" + len + ",宽度是:" + wid);
        }
    }
    

    ShapeRectTest.java

    package cn.itcast.day01.demo13;
    
    public class ShapeRectTest {
        public static void main(String[] args) {
            Shape s1 = new Shape(10, 20);
            s1.show();
            System.out.println("--------------------------------");
    
            Rect r1 = new Rect(30, 40, 50, 60);
            r1.show();
            System.out.println("--------------------------------");
    
            Shape sr = new Rect(70, 80, 90, 100);
            //当Rect类中没有重写show方法时,下面的代码调用shape类中的show方法
            //当Rect类中重写show方法后,下面的代码在编译阶段调用Shape类的方法,在运行阶段调用Rect类中的show方法
            sr.show();
            System.out.println("--------------------------------");
        }
    }
    

    编译并执行ShapeRectTest.java

    横坐标:10,纵坐标:20
    --------------------------------
    横坐标:30,纵坐标:40
    长度是:50,宽度是:60
    --------------------------------
    横坐标:70,纵坐标:80
    长度是:90,宽度是:100
    --------------------------------
    

    子类继承父类,当子类重写父类的方法后,代码在编译阶段调用父类的方法,运行阶段调用子类的方法。

    多态的特点

    引用数据类型之间转换的方式

    ShapeRectTest.java

    package cn.itcast.day01.demo13;
    
    public class ShapeRectTest {
        public static void main(String[] args) {
            Shape sr = new Rect(70, 80, 90, 100);
            int ib = ((Rect) sr).getLen(); //强制转换:父类转子类。大到小的转换。
            System.out.println("--------------------------------");
        }
    }
    

    引用数据类型转换的注意事项

    引用数据类型之间的转换必须发生在父子类之间,否则编译报错。

    目前已经学过的异常有:
    	ArithmeticException算术运算异常
    	ArrayIndexOutOfBoundsException数据越界异常
    	NullPointerException空指针异常
    	ClassCastException类型转换异常
    

    Circle.java

    package cn.itcast.day01.demo13;
    
    public class Circle extends Shape{
    }
    

    ShapeRectTest.java

    package cn.itcast.day01.demo13;
    
    public class ShapeRectTest {
        public static void main(String[] args) {
            Shape sr = new Rect(70, 80, 90, 100);
            int ib = ((Rect) sr).getLen(); //强制转换:父类转子类。大到小的转换。
            
            if(sr instanceof Circle) {
                System.out.println("可以放心转换了");
                Circle c1 = (Circle)sr;
            } else {
                System.out.println("强转有风险,操作需谨慎!");
            }
            System.out.println("--------------------------------");
        }
    }
    

    多态的实际意义

    首先看下面的例子:

    ShapeTest.java

    package cn.itcast.day01.demo13;
    
    public class ShapeTest {
        public static void draw(Rect r) {
            r.show();
        }
    
        public static void draw(Circle c) {
            c.show();
        }
    
        public static void main(String[] args) {
            Rect r1 = new Rect(1, 2, 3, 4);
            ShapeTest.draw(r1);
    
            System.out.println("-------------------");
    
            Circle c1 = new Circle(5, 6, 7);
            ShapeTest.draw(c1);
        }
    }
    
    //执行结果:
    横坐标:1,纵坐标:2
    长度是:3,宽度是:4
    -------------------
    横坐标:5,纵坐标:6
    半径是:7
    

    Rect和Circle都是Shape的子类,在ShapeTest类中,当需要画出Rect(矩形)和Circle(圆形)时,我们需要分别写两个draw方法,形参分别是RectCircle对象,在调用各自的show方法。这样显得极其繁琐,有相当多的冗余代码。

    于是我们这样改写代码:ShapeTest.java

    package cn.itcast.day01.demo13;
    
    public class ShapeTest {
        public static void draw(Shape s) {
            //编译阶段调用父类的版本,运行阶段调用子类重写以后的版本
            s.show();
        }
    
        public static void main(String[] args) {
            Shape r1 = new Rect(1, 2, 3, 4);
            ShapeTest.draw(r1);
    
            System.out.println("-------------------");
    
            Shape c1 = new Circle(5, 6, 7);
            ShapeTest.draw(c1);
        }
    }
    

    改写后的代码就使用到了多态的一个应用场景:父类的引用指向子类的对象,形成了多态,此时编译阶段调用父类的版本,运行阶段调用子类重写以后的版本。

    所以说,多态的实际意义在于屏蔽不同子类的差异性实现通用的编程带来不同的效果。

    抽象方法和抽象类的概念

    实例:

    AbstractTest.java

    package cn.itcast.day01.demo13;
    
    //抽象类:用abstract修饰类
    public abstract class AbstractTest {
        private int cnt;
    
        public AbstractTest() {
        }
    
        public AbstractTest(int cnt) {
            setCnt(cnt);
        }
    
        public int getCnt() {
            return cnt;
        }
    
        public void setCnt(int cnt) {
            this.cnt = cnt;
        }
        
        //抽象方法:用abstract修饰方法
        public abstract void show();
    }
    

    抽象类的实际意义

    写一个类继承AbstractTest类:

    package cn.itcast.day01.demo13;
    
    public class SubAbstractTest extends AbstractTest {
        @Override
        public void show() {
            System.out.println("子类SubAbstractTest继承抽象类AbstractTest之后,子类必须重写父类的抽象方法show");
        }
    
        public static void main(String[] args) {
            SubAbstractTest sat = new SubAbstractTest();
            sat.show();
    
            System.out.println("--------------------");
    
            AbstractTest at = new SubAbstractTest();
            at.show();
        }
    }
    
    //执行结果:
    子类SubAbstractTest继承抽象类AbstractTest之后,子类必须重写父类的抽象方法show
    --------------------
    子类SubAbstractTest继承抽象类AbstractTest之后,子类必须重写父类的抽象方法show
    

    所以抽象类的实际意义是:

    抽象类的应用

    Account.java

    package cn.itcast.day01.demo13;
    
    public abstract class Account {
        private double money;
    
        public Account() {
        }
    
        public Account(double money) {
            setMoney(money);
        }
    
        public double getMoney() {
            return money;
        }
    
        public void setMoney(double money) {
            if (money >= 0) {
                this.money = money;
            } else {
                System.out.println("账户金额必须大于等于0!");
            }
        }
    
        public abstract double getLiXi();
    }
    

    FixedAccount.java

    package cn.itcast.day01.demo13;
    
    public class FixedAccount extends Account {
        @Override
        public double getLiXi() {
            return getMoney() * 0.03 * 1;
        }
    
        public FixedAccount(double money) {
            super(money);
        }
    
        public FixedAccount() {
        }
    
        public static void main(String[] args) {
            Account acc = new FixedAccount(1000);
            double res = acc.getLiXi();
            System.out.println("计算的利息是:" + res);
        }
    }
    
    //执行结果:
    计算的利息是:30.0
    

    一些注意事项

    • private和abstract不能共同修饰一个方法
    • final和abstract不能共同修饰一个方法
    • static和abstract不能共同修饰一个方法

    接口的基本概念

    InterfaceTest.java

    package cn.itcast.day01.demo13;
    
    //自定义一个接口,关键字:interface
    public interface InterfaceTest {
        public static final int cnt1 = 1;
        /*public static final*/ int cnt2 = 1;   //只能有常量
    
        private void show() {}  //从java9开始允许接口中出现私有方法
    
        public abstract void show2(); //接口中只能有抽象方法(新特性除外),public abstract关键字可以省略,但是建议写上
    }
    

    接口的实际意义

    弥补子类无法继承多个父类的缺点:子类可以实现多个接口。

    Metal.java

    package cn.itcast.day01.demo14;
    //金属类
    public interface Metal {
        //自定义抽象方法描述发光行为
        public abstract void shine();
    }
    

    Money.java

    package cn.itcast.day01.demo14;
    //货币类
    public interface Money {
        //自定义抽象方法描述购物行为
        public abstract void Buy();
    }
    

    Gold.java

    package cn.itcast.day01.demo14;
    
    //黄金类
    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 m1 = new Gold();
            m1.shine();
    
            Money m2 = new Gold();
            m2.Buy();
        }
    }
    
    //执行结果:
    发出了金黄色的光芒...
    买了好多好吃的。。。
    

    类和接口之间的关系

    先来写一个实例:

    接口只能继承接口,不能继承普通类。

    Runner.java:

    package cn.itcast.day01.demo15;
    
    public interface Runner {
        public abstract void Run();
    }
    

    Hunter.java:

    package cn.itcast.day01.demo15;
    
    public interface Hunter extends Runner{
        public abstract void Hunt();
    }
    

    Man.java:

    package cn.itcast.day01.demo15;
    
    public class Man implements Hunter {
        @Override
        public void Hunt() {
            System.out.println("正在追捕一只小白兔...");
        }
    
        @Override
        public void Run() {
            System.out.println("被人追赶,正在玩命逃跑...");
        }
    
        public static void main(String[] args) {
            //声明接口类型的引用执行实现类的对象,形成了多态
            Runner runner = new Man();
            runner.Run();
    
            Hunter hunter = new Man();
            hunter.Hunt();
        }
    }
    

    执行结果:

    被人追赶,正在玩命逃跑...
    正在追捕一只小白兔...
    

    接口和抽象类的主要区别

    Hunter.java

    package cn.itcast.day01.demo15;
    
    public interface Hunter extends Runner {
        public abstract void Hunt();
    
        //增加非抽象方法
        public default void show1() {
            System.out.println("这里仅仅是接口类的默认功能,实现类可以自由选择是否重写!");
        }
    
        //增加静态方法,隶属于类层级,也就是接口层级
        public static void test() {
            System.out.println("这里是静态方法,可以直接通过接口名. 的方式调用,省略对象的创建");
        }
    }
    
  • 相关阅读:
    div+css与table布局
    自动刷新网页效果
    Spring框架之Filter应用,filter可以使用spring注入资源
    http://localhost:8080/hohode
    java jacob 操作word 文档,进行写操作,如生成表格,添加 图片(这个不错,可以拿来直接用,非常好)
    java 填充word中的表格
    360抢票
    easyui 时间段校验,开始时间小于结束时间,并且时间间隔不能超过30天
    java操作word示例
    FastStone Capture 注册码 序列号
  • 原文地址:https://www.cnblogs.com/haitaoli/p/13789269.html
Copyright © 2011-2022 走看看