Java面向对象三剑客之多态

        多态是面向对象三大特性中最抽象、最难以理解的一个部分,但也是最关键的一部分、掌握好多态,就能在开发中减少代码冗余、提高代码的扩展性,极大的提高你的开发效率。

        首先,我们要知道多态的基本概念是什么:多态指的是,相同的方法,在被不同对象调用时,会产生不同的效果,同一个对象可以指向多种实际的类型。

        多态其实是一种现象,在其他地方也有所体现,比如,你在csgo中鼠标右键点击是开镜,而在lol中鼠标右键点击则是操控人物移动。同一个操作,因为你所处的环境不同,呈现出不同的效果,这其实也是多态的另一种体现。那么言归正传。既然是一种现象,那么产生这个现象一定会有前提条件,那么我们就来看看多态的产生条件:

多态的产生条件

多态产生的前提分别是:

1.要有继承的关系

2.子类要重写父类的方法。

3.父类引用指向子类对象(或父类形参调用子类实参)

        只要满足前两个条件,那么当父类引用指向子类对象时,多态就已经产生了。根据这三个条件分析,多态一定是在两个有继承关系的类之间产生的。那么多态究竟是什么样子呢?

        下面我们通过代码,来直观的感受,一定要认真了,多态是十分抽象的。

猫狗演示多态(父类引用指向子类对象)

我首先定义一个Animal类,他是动物的父类,其中包含了一些属性和方法:

public class Animal{
     String name;
     int age;
 ​
     public void eat(){
         System.out.println("动物吃饭");
     }
 ​
 }

然后我定义一个Cat类和一个Dog类,他们都继承自Animal:

class Cat extends Animal{
     @Override
     public void eat() {
         System.out.println("猫吃鱼");
     }
     public void getMouse(){
         System.out.println("猫抓老鼠");
     }
 }
 class Dog extends Animal{
 ​
     @Override
     public void eat() {
         System.out.println("狗吃骨头");
     }
      public void lookDoor(){
         System.out.println("狗看门");
     }
     
 }

        在这里,子类都对父类的eat方法进行了重写,他们有不同的吃饭方法,同时他们也有自己特有的方法,这时,我使用父类引用指向子类对象,多态就产生了,那么什么叫父类引用指向子类对象呢?

        平常,我们创建一个Cat对象应该是:Cat cat =new Cat(); 那么现在,父类引用指向子类对象,我们创建的时候就要这样:Animal an =new Cat();首先,他是一个Animal,其次,他是一只Cat。那么这个对象的eat方法显然,就是Cat的eat方法,也就是猫吃鱼。

        我们使用一个测试类来看:

 public class Test{
     public static void main(String[] args) {
         Animal an =new Cat();
         an.eat();
         Animal an1=new Dog();
         an1.eat();
     }
 }   

分别是一个猫和一个狗,输出的效果是:

 

可以看到,同一个方法,不同的对象调用,结果是不一样的。多态就是这样的效果。

向下转型

需要注意的是,多态产生的对象只能调用子类重写父类的方法,而不能调用子类特有的方法,也就是说,猫的getMouse方法和狗的lookDoor方法他是没有办法调用的:

 

可以看到,他们找不到这些方法,那么如果我们需要它调用到这些方法,怎么办呢?这就需要一个操作:向下转型,也就是将Animal类型的Cat对象转换称为Cat类型的Cat对象,这样就能访问到子类中的特有方法了。

向下转型的语法是:Cat cat =(Cat)an;这样我们就会得到一个cat对象,这个对象就可以访问特有的方法:

 public class Test{
     public static void main(String[] args) {
         Animal an =new Cat();
         an.eat();
         Animal an1=new Dog();
         an1.eat();
         
         Cat cat=(Cat) an;
         cat.eat();
         cat.getMouse();
         
         Dog dog=(Dog)an1;
         dog.eat();
         dog.lookDoor();
         
         
     }
 }   

这样就不会报错了,运行一下看效果:

 

可以看到,我们可以访问到抓老鼠和看门这两个子类特有方法了。

注意,猫不可以转成狗,也就是说,父类可以转成子类,但兄弟之间不能互转。如果兄弟互转,语法不会报错,但是运行时会报错。

使用多态减少代码冗余

上文提到了,多态可以提高代码的扩展性,减少代码冗余,这是在哪里体现的呢?下面我们继续用例子演示一下。

我们继续沿用上文的猫狗案例,不同的是,我们给测试类中加入一个方法:

 public class Test{
     public static void main(String[] args) {
         Cat cat =new Cat();
         an.eat();
         Dog dog=new Dog();
         an1.eat();  
         
     }
     
     public static void animalEat(Animal animal){
         animal.eat();
     }
 }   

就是这个animalEat方法,然后我们让他传一个Animal参数进来,也就是一个Animal 的对象,这样做有什么好处呢?

大家观察一下main方法中的代码我每次想要调一个动物的方法,我们就得new一个该动物的对象,然后用这个对象来调用方法,这样效率太慢,而且重复代码很多,如果我需要调很多动物的方法,那么我还得一个一个new,一个一个调方法。那么有了这个方法之后,我们看代码可以改良成什么样子:

 public class Test{
     public static void main(String[] args) {
         animalEat(new Dog());
         animalEat(new Cat());
         
     }
     
     public static void animalEat(Animal animal){
         animal.eat();
     }
 } 

是不是显得清爽了一些,当然,我们这里只有两个动物,假如动物很多,那效果会更加明显。

先看一下效果:

        那么分析一下代码,在方法中我们传的是匿名对象,而且是Cat和Dog类的匿名对象,而在方法的参数列表中定义的是Animal类型的对象,也就是说,Cat和Dog是Animal的子类,那么,他们的对象也是可以作为参数传入的,并且方法使用的还是子类自己的方法,这就是父类形参引用子类实参,不单是Cat和Dog,所有继承Animal的子类,他们的对象都可以被传入。

        这样大家都是Animal,大家都可以共用一个方法,不用各自调各自的方法了,这就提高了代码的拓展性,我想要一个新的动物的eat方法,那么我只需要让这个动物类继承Animal,那么他的对象也就可以传入这个方法了。十分简便快捷。

总结

        作为程序员来说,我们肯定希望自己的工作量降低,或者说将重复的代码降到最低,其实就是懒,但是懒也是有好处的,人们因为懒得走路所以发明了汽车,因为懒得带纸币所以发明了微信支付,可以说懒让我们进步,那我们是真的懒吗?其实我们只是不愿意在重复简单的事情上浪费精力罢了,程序员更是如此,不论是刚开始的继承,还是现在的多态,他们都是起到一个提高代码拓展性,降低代码冗余的作用,也都是十分好用的语法,让我们的代码灵活了起来,简便了起来。那么多态的作用还不止于此,在后面的学习中,我们会接触到抽象类和接口,他们都无法直接创建对象,都是通过多态来调用方法的,这能够很简便的为我们提供服务,不过这都是后话了。

        看到这里,我们已经总结了面向对象的三剑客,你也应该掌握到面向对象的大部分精髓了,可能有的人还是觉得自己看了半天,还是云里雾里,不要着急,我们继续往后学,面向对象十分的抽象,重在理解,只要你理解了,那么你马上就会觉得简单起来了,一遍就能理解的人少之又少,等我们学到后面,然后运用那时候的知识反过头来看,那么你就会觉得茅塞顿开了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值