13多态

作者: 十一_2bef | 来源:发表于2018-05-29 16:53 被阅读0次

    问题

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

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

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

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

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

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

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

    宠物父类、

    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("宠物的自白:\n我的名字叫" + 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();         
        }
    }
    

    测试类的改变

    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 {
        String name;
    
        public abstract int calcSalary();
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    开发人员

    public class Developer extends Employee {
        int salary;//每月工资
    
        public Developer(int salary)
        {
            this.salary = salary;
        }
    
        @Override
        public int calcSalary() {
            return salary;
        }
    }
    
    

    硬件工程师

    public class HardwareEngineer extends Employee{
    
        int num;
    
        public HardwareEngineer(int num)
        {
            this.num = num;
        }
    
        @Override
        public int calcSalary() {
            return 50*num;
        }
    }
    
    

    小时工

    public class HourWorker extends Employee {
        int hours;
        public HourWorker(int hours)
        {
            this.hours = hours;
        }
    
        @Override
        public int calcSalary() {
            return 30*hours;
        }
    }
    

    销售

    int base_sal;
        int comm;
    
        public SalesMan(int base_sal, int comm)
        {
            this.base_sal = base_sal;
            this.comm = comm;
        }
    
        @Override
        public int calcSalary() {
            return base_sal + comm;
        }
    }
    
    

    主类

    public class Main {
        public static void main(String[] args) {
    
            int index = 0;
            Employee[] employees = new Employee[6];
            employees[index++] = new Developer(10000);
            employees[index++] = new SalesMan(2000,5000);
            employees[index++] = new HardwareEngineer(120);
            employees[index++] = new HourWorker(200);
            employees[index++] = new HourWorker(300);
            employees[index] = new HourWorker(500);
            int sum = 0;
            for(Employee employee : employees)
            {
                sum += employee.calcSalary();
            }
            System.out.println(sum);
        }
    }
    
    

    相关文章

      网友评论

          本文标题:13多态

          本文链接:https://www.haomeiwen.com/subject/kleajftx.html