zoukankan      html  css  js  c++  java
  • 面向对象三大特性-多态的思考

      无论是python语言,还是java语言都有着面向对象的特性,而面向对象三大特性(封装,继承,多态)中封装和继承是比较容易理解的,多态的话自己一直处于一个似懂非懂的状态。比如一些概念性的东西:

      多态的要点:
          1. 多态是方法的多态,不是属性的多态(多态与属性无关)。
          2. 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。
          3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
      
      对象类型的转换:
    1. 向上可以自动转换类型,由子类转换成父类!
    2. 向下(由父类转换成子类)强制类型转换!以调用该对象特有的方法!

      这些概念性的知识都明白了,但是对于多态的意义及在实际代码中的作用还是很模糊的,因此重新梳理思考了下。

      模拟了以下一个场景:

      人可以养一些宠物,可以喂养宠物,可以逗宠物玩。

      (人类,宠物类,人的一些方法,宠物的一些方法)

      如果是没有使用多态的情况下,代码应该是这样的:

    public class PersonNotUsePolymorphic {
        public static void main(String[] args) {
    
            Dog2 dog2 = new Dog2();
            Cat2 cat2 = new Cat2();
            Bird2 bird2 = new Bird2();
            Chicken2 chicken2 = new Chicken2();
    
            PersonNotUsePolymorphic person = new PersonNotUsePolymorphic();
    
            person.feedDog(dog2);
            person.feedCat(cat2);
            person.makeBirdFly(bird2);
            person.makeChickenFly(chicken2);
    
        }
       // 喂狗
        public void feedDog(Dog2 dog2) {
            dog2.eat();
        }
       // 喂猫
    public void feedCat(Cat2 cat2) { cat2.eat(); }    // 放飞小鸟 public void makeBirdFly(Bird2 bird2) { bird2.fly(); }    // 放飞小鸡 public void makeChickenFly(Chicken2 chicken2) { chicken2.fly(); } } class Dog2 { void eat() { System.out.println("骨头"); } } class Cat2 { void eat() { System.out.println("吃鱼"); } } class Bird2 { void eat() { System.out.println("吃虫子"); } void fly() { System.out.println("i can fly i am bird"); } } class Chicken2 { void eat() { System.out.println("吃玉米"); } void fly() { System.out.println("i can fly i am chicken"); } }

      可以看到有狗,猫,鸟,鸡四种宠物,它们都可以吃东西,但是鸟和鸡可以飞,如果没有多态,人如果要喂养宠物或者放飞宠物就需要写多个方法,有几个宠物就要写几个方法,如果以后家里又多了好多宠物,就要写好多的方法。

      并且宠物之间的关系,相关的动作属性都没有层次关系,非常的独立,是面向对象了(如果再多有几个宠物,就更无法梳理之间的关系共性),但是并没有体现面向对象的特性

      我们看下如果使用面向对象的思想,应该如何处理。

    public class PersonUsePolymorphic {
    
        public static void main(String[] args) {
            PersonUsePolymorphic p = new PersonUsePolymorphic();
            Animal dog = new Dog();
            p.feed(dog);
            Animal cat = new Cat();
            p.feed(cat);
            FlyAnimal bird = new Bird();
            p.makeAnimalFly(bird);
            FlyAnimal chicken = new Chicken();
            p.makeAnimalFly(chicken);
        }
    
        public void feed(Animal animal) {
            animal.eat();
        }
    
        public void makeAnimalFly(FlyAnimal flyAnimal) {
            flyAnimal.fly();
        }
    }
    
    /**
     * 抽离抽象类动物
     * 抽离出抽象方法:吃东西(必须实现)
     * 可以很清晰看出公共的特性,缕出层次关系
     */
    abstract class Animal{
        abstract void eat();
    }
    
    /**
     * 抽离出飞行接口(java不能多继承)
     * 因为不是所有动物都会飞,不能在抽象类中作为抽象方法实现
     * 实现了飞行接口就必须实现接口里面的方法,为什么不把fly方法直接放到FlyAnimal中呢,因为飞行只是一个接口行为,并不一定只有动物会飞,飞机也可以飞,气球也可以飞
     * 接口只是个规范行为,遵守了这个规范都可以实现里面的方法
     */
    interface Fly{
        void fly();
    }
    
    /**
     *  狗狗继承动物类,实现eat方法就好
     */
    class Dog extends Animal{
        void eat() {
            System.out.println("骨头");
        }
    }
    
    class Cat extends Animal{
        void eat() {
            System.out.println("吃鱼");
        }
    }
    
    /**
     *  抽离出公共类飞行动物继承自动物,实现fly接口
     */
    class FlyAnimal extends Animal implements Fly{
    
        @Override
        void eat() {
            System.out.println("吃东西");
        }
    
        @Override
        public void fly() {
            System.out.println("i can fly");
        }
    }
    
    /**
     *  飞行类的动物就可以继承飞行动物类,重写eat fly方法
     */
    class Bird extends FlyAnimal{
        public void fly() {
            System.out.println("i can fly,i am bird");
        }
    
        void eat() {
            System.out.println("吃虫子");
        }
    }
    
    class Chicken extends FlyAnimal{
        void eat() {
            System.out.println("玉米");
        }
    
        public void fly() {
            System.out.println("i can fly, i am chicken");
        }
    }

      可以看到进行面向对象的思路的改进后代码量并没有减少,但是整体的层次就非常明显了。

      如果大多数程序都按照第一次那样来写,底层类的设计不合理维护起来非常麻烦,上层person类调用起来也是非常繁琐,底层增加一个类,person增加一个方法。

      在第二次的程序里,虽然在类的设计上代码量多了,但是把每个类的共性、方法都抽离出来,再进行维护起来关系层次很清晰,而修改类底层设计,person类根本不需要做改动。

      经过两次的代码比对应该能发现多态的好处了,也理解了多态在面向对象中发挥的作用。如果仅仅有个模糊的概念,在看一些源码的时候非常的吃力,因为一些源码运用了大量的设计模式及面向对象的思想,看一个方法会发现跳过来跳过去还不知道到底是做什么用的,只有将最基础的东西学明白学扎实了才能更好的进行程序设计。

  • 相关阅读:
    MJExtension的使用
    Swift
    2月22号 UITableView
    1月25号 CALayer
    1月22号 animation—1
    1月22号 KVC KVO
    2016.01.22 简单动画
    2016.01.22 KVC&KVO
    2016.01.22 单例模式(Singleton)
    2016.01.21 UITabBarController
  • 原文地址:https://www.cnblogs.com/dreamyu/p/12019860.html
Copyright © 2011-2022 走看看