多态的概念
多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态。
总的来说;就是同一件事,发生在不同的对象上产生不同的结果
多态实现的条件
在Java中实现多态,必须满足以下条件;
1.在继承体系下
2.子类必须重写父类的方法
3.通过父类的应用调用重写的方法
在了解多态前我们得先了解继承,向上转型和重写
1.继承我们上节博客有讲过,这里不再重新讲述了。 接下来我们先了解向上转型和重写
向上转型和向下转型
向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
格式:父类类型 对象名=new子类类型()Basebase=newSub();右边的Sub是子类型被一个父类 的类型引用,使小范围向大范围转换,称为向上转型
向上转型有三种使用场景;
1.直接赋值
2.方法传参
3方法返回
1.直接赋值
publicclassAnimal{publicAnimal(Stringname,intage){this.name=name;this.age=age;}Stringname;intage;}publicclassDogextendsAnimal{publicDog(Stringname,intage){super(name,age);}publicstaticvoidmain(String[]args){Animalanimal=newDog("旺财",10);animal.eat();}}由向上转型直接给赋值,将子类的对象直接赋值给父类对象
2.方法传参
classAnimal{voideat(){System.out.println("Animal eats");}}classDogextendsAnimal{@Overridevoideat(){System.out.println("Dog eats bones");}}publicclassMain{staticvoidfeed(Animalanimal){// 参数为父类类型animal.eat();}publicstaticvoidmain(String[]args){Dogdog=newDog();feed(dog);// 向上转型:Dog -> Animal}}这里给feed(Animal animal)了一个父类的形参,给子类实例话了之后可以将子类的变量调用到函数中。
注;形参为父类引用,可以接受任意系类对象。
方法返回
classAnimal{publicvoideat(){System.out.println("动物进食");}}classDogextendsAnimal{@Overridepublicvoideat(){System.out.println("狗吃骨头");}// 子类独有方法:父类中无声明publicvoidbark(){System.out.println("狗汪汪叫");}}// 3. 测试类:包含返回父类类型的方法publicclassReturnTest{// 方法声明返回父类Animal,实际返回子类DogpublicstaticAnimalgetAnimal(){// 自动向上转型:Dog -> AnimalreturnnewDog();}publicstaticvoidmain(String[]args){// 接收返回值:父类引用指向子类对象(典型向上转型)Animalanimal=getAnimal();animal.eat();方法返回的本质来说和直接赋值一样的。
向下转型
概念;将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。
publicclassAnimal{Stringname;intage;voideat(){System.out.println(this.name+"正在吃饭...");}}publicclassDogextendsAnimal{voideat(){System.out.println(this.name+"正在吃狗粮...");}}publicclasstest{publicstaticvoidmain(String[]args){Animalanimal=newDog();animal.name="旺财";animal.eat();}}向上转型的优点;可以将代码更灵活
向下转型的缺点;不可以调用子类特有的方法
动态绑定
publicclassAnimal{publicStringname;publicintage;publicAnimal(Stringname,intage){this.name=name;this.age=age;}publicvoideat(){System.out.println(this.name+"正在吃饭...");}}publicclassCatextendsAnimal{publicCat(Stringname,intage){super(name,age);}publicvoideat(){System.out.println(this.name+"正在吃猫粮");}}publicclassDogextendsAnimal{publicDog(Stringname,intage){super(name,age);}publicvoideat(){System.out.println(this.name+"正在吃狗粮");}}publicclassTest{publicstaticvoidfunc(Animalanimal){animal.eat();}publicstaticvoidmain(String[]args){Dogdog=newDog("大黄",5);func(dog);System.out.println("===============");Catcat=newCat("咪咪",3);func(cat);}}由上面的代码可以了解到在同一个函数中调用的参数不同是所产生的结果也是不一样的。即同一个方法不同的对象去做的时候,产生的结果也是不同的则称为动态绑定
多态(Polymorphism)的实现确实依赖于动态绑定(Dynamic Binding)。这是 Java 面向对象编程的核心机制之一。
静态绑定
publicclassTest{publicstaticintadd(inta,intb){returna+b;}publicstaticintadd(inta,intb,intc){returna+b+c;}publicstaticvoidmain(String[]args){add(1,2);add(1,2,3);}}静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。
多态的优点
多态可以运用在循环中来达到代码的简便避免使用大量if-else的循环
例如 ;首先定义下面几个类。
classShape{publicvoiddraw(){System.out.println("画图形!");}}classRectextendsShape{@Overridepublicvoiddraw(){System.out.println("♦");}}classCycleextendsShape{@Overridepublicvoiddraw(){System.out.println("●");}}classFlowerextendsShape{@Overridepublicvoiddraw(){System.out.println("❀");}}我们现在需要打印的不是一个形状了, 而是多个形状. 如果不基于多态, 实现代码如下
publicstaticvoiddrawShapes(){Rectrect=newRect();Cyclecycle=newCycle();Flowerflower=newFlower();String[]shapes={"cycle","rect","cycle","rect","flower"};for(Stringshape:shapes){if(shape.equals("cycle")){cycle.draw();}elseif(shape.equals("rect")){rect.draw();}elseif(shape.equals("flower")){flower.draw();}}}如果使用多态实现的话则不需要这么多的if-else循环
publicstaticvoiddrawShapes(){// 我们创建了一个 Shape 对象的数组.Shape[]shapes={newCycle(),newRect(),newCycle(),newRect(),newFlower()};for(Shapeshape:shapes){shape.draw();}}