• Java中有三大特性:继承、封装、多态,每一个Java的学习者都知道,但是其中的实现方法是什么呢?我从来没有去深究过,这次面试开头就被问住了,后面全程懵,自然是被刷的下场,还是要注意基础的学习啊。

什么是多态?

        父类类型的对象指向子类创建的对象,使用该变量调用父类中一个被子类重写的方法,则父类中的方法出现出不同的行为特征,这就是多态。
        简单的来说就是编译时方法行为表现为父类中的方法,运行时方法行为表现为子类中重新该方法的行为特征。

举个简单的例子:


/*
对象的多态性:动物 x = new 猫();
函数的多态性:函数重载、重写
1、多态的体现
		父类的引用指向了自己的子类对象
		父类的引用也可以接收自己的对象
2、多态的前提
		必须是类与类之间只有关系,要么继承或实现
		通常还有一个前提,存在覆盖
3、多态的好处
		多态的出现大大的提高了程序的扩展性
4、多态的弊端
		只能使用父类的引用访问父类的成员
5、多态的应用
6、注意事项
*/
 
/*
需求:
猫,狗。
*/
 
abstract class Animal
{
	abstract void eat();
}
 
class Cat extends Animal
{
	public void eat()
	{
		System.out.println("吃鱼");
	}
	public void catchMouse()
	{
		System.out.println("抓老鼠");
	}
}
 
class Dog extends Animal
{
	public void eat()
	{
		System.out.println("吃骨头");
	}
	public void kanJia()
	{
		System.out.println("看家");
	}
}
 
class DuoTaiDemo
{
	public static void main(String[] args)
	{
		function(new Cat());
		function(new Dog());
		
		Animal a = new Cat();//向上转型
		a.eat();
		
		Cat c = (Cat)a;//向下转型
		c.catchMouse();
		
		
	}
	
	public static void function(Animal a)
	{
		a.eat();
		//用于子类型有限
		//或判断所属类型进而使用其特有方法
		if(a instanceof Cat)
		{
			Cat c = (Cat)a;
			c.catchMouse();
		}
		else if(a instanceof Dog)
		{
			Dog c = (Dog)a;
			c.kanJia();
		}
	}
	
	
}


为什么使用多态?

1、实现代码的复用,避免代码的冗余;

2、减少代码之间的关联性,即耦合度,方便后期对代码的修改、功能的改善;

3、能够通过重写子类的方法,使不同的对象具有不同的功能,扩展了代码。


多态的实现方式

1、接口

辐射拓展,如果接口中新增加了方法,则需要修改所有实现此接口的实现方法。

    ①接口中的变量会被隐式地指定为public static final变量。

    ②接口中的方法都是抽象方法。

    ③一个类可继承多个接口。

    ④实现接口需实现接口中的所有方法。

public interface InterDemo(){
    void setData();
    int getCount();
}
 
public class InterImpl implements InterDemo(){
    
    @Override
    public void setData(){
        //....
    }
    
    @Override
    public void getCount(){
        //....
    }
}


2、抽象类

延伸拓展,如果在抽象类中增加方法,底层所有继承此类的子类都不需要修改,如果需调用,则直接调用父类方法即可。

       抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象,所以抽象类是一个在项目开始就得确定好的公共类。

interface FlyInter {
    void fly();
}
 
public abstract class FlyGroups implements FlyInter{
    public String name = "飞行类";
    public String getName(){
        return name;
    }
    abstract void fun();
}
 
 
public class Airplane extends FlyGroups {
    @Override
    public void fly() {
        String name = super.getName();
        System.out.println(name);
    }
    @Override
    public void fun(){
    }
}


3、继承父类进行方法重写

纵向拓展,子类可以重写父类的方法进行拓展

public class Parent{
 
    public void fun(){
    }
}
 
public class Child extends Parent{
    @Override
    public void fun(){
        //子类的重写
    }
}


4、同一个类进行方法重载

横向拓展,方法的重写需参数不同、参数个数不同、返回值不同。

public void init(String name,int i){
        
}
    
public void init(int i,String name){
        
}
    
public void init(){
        
}
    
public int init(){
        
}


扩展   静态绑定和动态绑定

JVM方法调用的静态(static binding) 和动态绑定机制(auto binding) 

 动态绑定机制

     下面代码有三个概念:多态 、方法覆盖 、方法重载。

     这种在程序运行过程中,通过动态创建的对象的方法表来定位方法的方式,我们叫做 动态绑定机制 也是多态的体现。

//被调用的父类  
class Father{  
    public void f1(){  
        System.out.println("father-f1()");  
    }  
        public void f1(int i){  
                System.out.println("father-f1()  para-int "+i);  
        }  
}  
//被调用的子类  
class Son extends Father{  
    public void f1(){ //覆盖父类的方法  
        System.out.println("Son-f1()");  
    }  
        public void f1(char c){  
                System.out.println("Son-s1() para-char "+c);  
        }  
}  
  
public class AutoCall{  
    public static void main(String[] args){  
        Father father=new Son(); //多态  
        father.f1(); //打印结果: Son-f1()  
    }  


静态绑定机制

在编译阶段就能够确定调用哪个方法的方式,我们叫做 静态绑定机制,new 类调用方法就是静态绑定。