• Java零基础系列教程013Java多态


    配套视频教程

    本文B站配套视频教程

    问题

    宠物饿了,需要主人给宠物喂食

    • 不同宠物吃的东西不一样,狗吃骨头,企鹅吃鱼

    • 不同宠物恢复后体力值不一样

    • 狗狗类
      增加狗狗吃食的方法

    • 企鹅类
      增加企鹅吃食的方法

    • 创建主人类
      编写给狗狗喂食的方法
      编写给企鹅喂食的方法

    • 编写测试方法
      调用主人类给狗狗喂的方法
      调用主人类给企鹅喂的方法

    宠物父类

    public abstract class Pet {
    	private String name = "无名氏";// 昵称
    	private int health = 100;// 健康值
    	private int love = 0;// 亲密度
    	
    	/**
    	 * 抽象方法eat(),负责宠物吃饭功能。
    	 */
    	public abstract void eat();
    	
    	/**
    	 * 有参构造方法。
    	 * @param name  昵称
    	 */
    	public Pet(){
    		
    	}
    	
    	public Pet(String name) {
    		this.name = name;
    	}
    	
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public void setHealth(int health) {
    		this.health = health;
    	}
    
    	public void setLove(int love) {
    		this.love = love;
    	}
    
    	public String getName() {
    		return name;
    	}
    	public int getHealth() {
    		return health;
    	}
    	public int getLove() {
    		return love;
    	}
    	/**
    	 * 输出宠物信息。
    	 */
    	public void print() {
    		System.out.println("宠物的自白:
    我的名字叫" + this.name + 
    				",健康值是"	+ this.health + ",和主人的亲密度是"
    				+ this.love + "。");
    	}	
    }
    
    

    狗类

    public class Dog extends Pet {
    	private String strain;// 品种
    	/**
    	 * 有参构造方法。
    	 * @param name   昵称
    	 * @param strain   品种
    	 */
    	public Dog(String name, String strain) {
    		super(name); 
    		this.strain = strain;
    	}
    	public String getStrain() {
    		return strain;
    	}
    	/**
    	 * 重写父类的print方法。
    	 */
    	public void print(){
    		super.print(); //调用父类的print方法
    		System.out.println("我是一只 " + this.strain + "。");
    	}
    	
    	/**
    	 * 实现吃食方法。 
    	 */
    	public void eat() {
    		if(getHealth()>=100){
    			System.out.println("狗狗"+this.getName() +"吃饱了,不需要喂食了!");
    		}else{
    			this.setHealth(this.getHealth()+3);
    			System.out.println("狗狗"+this.getName() + "吃饱啦!健康值增加3。");
    		}
    	}
    }
    
    

    企鹅类

    public class Penguin extends Pet {
    	private String sex;// 性别
    	/**
    	 * 有参构造方法。
    	 * @param name 昵称
    	 * @param sex 性别
    	 */
    	public Penguin(String name, String sex) {
    		super(name);
    		this.sex = sex;
    	}
    	public String getSex() {
    		return sex;
    	}
    	/**
    	 * 重写父类的print方法。
    	 */
    	public void print() {
    		super.print();
    		System.out.println("性别是 " + this.sex + "。");
    	}
    	
    	/**
    	 * 实现吃食方法。 
    	 */
    	public void eat() {
    		if(getHealth()>=100){
    			System.out.println("企鹅"+this.getName() +"吃饱了,不需要喂食了!");
    		}else{
    			this.setHealth(this.getHealth()+5);
    			System.out.println("企鹅"+this.getName() + "吃饱啦!健康值增加3。");
    		}
    	}
    }
    
    

    主人类

    public class Master {
    	private String name = "";// 主人名字
    	private int money = 0; // 元宝数
    	/**
    	 * 有参构造方法。
    	 * @param name 主人名字
    	 * @param money 元宝数
    	 */
    	public Master(String name, int money) {
    		this.name = name;
    		this.money = money;
    	}
    	
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public void setMoney(int money) {
    		this.money = money;
    	}
    
    	public int getMoney() {
    		return money;
    	}
    	public String getName() {
    		return name;
    	}
    	/**
    	 * 主人给Dog喂食。
    	 */
    	public void feed(Dog dog) {
    		dog.eat();
    	}
    	/**
    	 * 主人给Penguin喂食。
    	 */
    	public void feed(Penguin pgn) {
    		pgn.eat();
    	}
    }
    

    测试类

    public class Test {
    	public static void main(String[] args) {
    		Dog dog = new Dog("欧欧", "雪娜瑞");
    		dog.setHealth(80); //设置健康值,以便正常喂食
    		Penguin pgn = new Penguin("楠楠", "Q妹");
    		Master master=new Master("王先生",100);
    		master.feed(dog);//主人给狗狗喂食
    		master.feed(pgn);//主人给企鹅喂食
    		pgn.setHealth(80); //设置健康值,以便正常喂食
    		master.feed(pgn);//主人再次给企鹅喂食
    	}
    }
    

    如果再领养新种类XXX的宠物,就需要给XXX喂食,怎么办?

    • 添加XXX类,继承Pet类,实现吃食方法
    • 修改Master类,添加给XXX喂食的方法
    public class Master {
           public void feed( Dog dog ) {
                  dog.eat();
           } 
    	public void feed( Penguin pgn ) {
                   pgn.eat();
            }
    	public void feed( XXX xxx ) {
                   xxx.eat();
            }
            … …
    }
    
    

    频繁修改代码,代码可扩展性、可维护性差,如何优化?
    使用多态优化设计

    参数都是Pet类的子类
    可否使用一个feed(Pet pet)实现对所有宠物的喂食?

    多态:同一个引用类型,使用不同的实例而执行不同操作

    使用多态实现思路

    • 编写父类
    • 编写子类,子类重写父类方法
    • 运行时,使用父类的类型,子类的对象
      Pet pet = new Dog();

    使用父类作为方法形参实现多态

    使用多态优化主人给宠物喂食

    public class Master {
    //使用父类作为方法形参 
        public void feed( Pet pet ) {
               pet.eat();         
        }
    }
    

    测试类的改变

    Pet pet = new Dog();
    Master master = new Master();
    master.feed( pet );//同一种操作方式,不同的操作对象 
    
    

    练习

    使用多态实现喂养宠物功能
    增加宠物猫并喂食,其健康值增加4

    计算一次租赁多辆汽车的总租金

    在继承章节汽车租赁系统的基础上,实现计算多种车辆总租金的功能
    现在有客户租用
    2辆宝马
    1辆别克商务舱
    1辆金龙(34)座
    租5天共多少租金?

    解题思路

    1、创建车的对象,放在数组中

    MotoVehile[] motos = new MotoVehile[4];
    motos[0] = new Car("宝马550i","京NY28588");
    motos[1] = new Car("宝马550i","京NNN328");
    motos[2] = new Car("别克林荫大道","京NY28588");
    motos[3] = new Bus("金龙",34);
    

    2 循环调用calcRent()方法,计算总租金

    public int calcTotalRent(MotoVehile[] motos,int days){
           int totalRent = 0; 
           for(int i=0;i<motos.length;++i){
                totalRent += motos[i].calRent(days);
           } 
           return totalRent;
    }
    

    假设新增了一种对外出租的车辆类型

    新购置了卡车,根据吨位,租金每吨每天50
    对系统进行扩展,计算汽车租赁的总租金

    解题思路

    1.创建卡车类,实现calcRent ()方法
    2.修改统计租金代码

    public abstract class MotoVehicle {
        private String no;//车牌号
        private String brand;//品牌
    
        abstract int calRent(int days);//计算租金
    
        public MotoVehicle()
        {
    
        }
        public MotoVehicle(String no, String brand)
        {
            this.no = no;
            this.brand = brand;
        }
    
        public String getNo() {
            return no;
        }
    
        public void setNo(String no) {
            this.no = no;
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    }
    
    public class Car extends MotoVehicle{
    
    
        public Car(String no, String brand)
        {
            super(no,brand);
    
        }
        @Override
        int calRent(int days) {
            if(getBrand().equals("宝马"))
            {
                return 500 * days;
            }
            else
            {
                return 600 * days;
            }
    
        }
    }
    
    public class Kache extends MotoVehicle {
        private int dunwei;//吨位
    
        public Kache(int dunwei)
        {
            this.dunwei = dunwei;
        }
    
        @Override
        int calRent(int days) {
            return 50*dunwei*days;
        }
    }
    

    不用多态的实现方式

       Car[] cars = new Car[3];
            cars[0] = new Car("辽A12345","宝马");
            cars[1] = new Car("辽B22222","别克");
            cars[2] = new Car("辽A62222","奔驰");
    
            Kache[] kaches = new Kache[2];
            kaches[0] = new Kache(1);//150
            kaches[1] = new Kache(4);//600
    
            int total = 0;
            for(int i = 0; i < cars.length; i++)
            {
                total += cars[i].calRent(3);
            }
            for(int i = 0; i < kaches.length; i++)
            {
                total += kaches[i].calRent(3);
            }
    
    
            System.out.println("总租金" + total);//5850
    

    使用多态实现

          MotoVehicle[] motoVehicles = new MotoVehicle[5];
            motoVehicles[0] = new Car("辽A12345","宝马");
            motoVehicles[1] = new Car("辽B22222","别克");
            motoVehicles[2] = new Car("辽A62222","奔驰");
            motoVehicles[3] = new Kache(1);
            motoVehicles[4] = new Kache(4);
            int total = 0;
            for(int i = 0; i < motoVehicles.length; i++)
            {
                total += motoVehicles[i].calRent(3);
            }
    
            System.out.println("总租金" + total);
    

    一个练习

    工资支付系统

    定义一个Employee抽象基类(name)

    公司有以下几种员工:

    开发人员:工资计算方式,每月固定工资
    销售人员:底薪+提成
    硬件工程师:生产零件,每个50元
    小时工:按工作时间付工资,每小时30元

    主类(测试类)

    创建不同类型的6名员工对象,计算他们应付的月工资之和

    public abstract class Employee {
    
        private String name;
    
        public Employee(String name)
        {
            this.name = "@" + name + "@" ;
        }
        protected abstract int paySalary();
    }
    
    //开发人员
    public class Developer extends Employee{
    
        private int salary;
    
        public Developer(String name, int salary)
        {
            super(name);
            this.salary = salary;
    
        }
    
        @Override//方法重写注解
        protected int paySalary() {
            return salary;
        }
    }
    
    
    //销售人员
    public class SaleMan extends Employee{
        private int salary;
        private int comm;//提成
    
        public SaleMan(String name, int salary, int comm)
        {
            super(name);
            this.salary = salary;
            this.comm = comm;
    
        }
        @Override
        protected int paySalary() {
            return salary + comm;
        }
    }
    
    //硬件工程师
    public class HardwareEngineer extends Employee {
        private int productCount;//每月生产的零件数量
    
        public HardwareEngineer(String name, int productCount)
        {
            super(name);
            this.productCount = productCount;
        }
    
        @Override
        protected int paySalary() {
            return 50*productCount;
        }
    }
    
    
    //小时工
    public class HourlyWorker extends Employee{
        private int hours;//这个月工作了多少小时
    
        public HourlyWorker(String name, int hours)
        {
            super(name);
            this.hours = hours;
        }
        @Override
        protected int paySalary() {
            return 30*hours;
        }
    }
    
    
    public class Boss extends Employee {
    
        public Boss(String name)
        {
            super(name);
        }
    
        @Override
        protected int paySalary() {
            return 200000;
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
    	// write your code here
    
            Employee[] employees = new Employee[6];
            employees[0] = new Developer("张二",5000);
            employees[1] = new Developer("张三",5000);
            employees[2] = new SaleMan("李四", 2000, 500);
            employees[3] = new HardwareEngineer("王五", 200);
            employees[4] = new HourlyWorker("冯六",200);
            employees[5] = new Boss("赵本山");
    
            //计算总工资
            int total = 0;
            for(int i = 0; i < employees.length; i++)
            {
                total += employees[i].paySalary();
            }
            System.out.println("总共需要支付" + total);
        }
    }
    
    
  • 相关阅读:
    7-6-有向图强连通分量的Kosaraju算法-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
    7-5-无向图生成树-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
    7-4-无向图的邻接多重表存储结构-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
    7-3-有向图的十字链表存储结构-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
    7-2-图的邻接表存储-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
    7-1-图、表的数组(邻接矩阵)表示法-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
    树和二叉树-第6章-《数据结构题集》习题解析-严蔚敏吴伟民版
    6-11-N皇后问题-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版
    6-10-幂集-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版
    6-9-哈夫曼树(HuffmanTree)-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版
  • 原文地址:https://www.cnblogs.com/songboriceboy/p/13757685.html
Copyright © 2020-2023  润新知