说说 Java 多态那些事儿~

2019-10-21  本文已影响0人  Vector_Wan

都说面向对象有三大特性:封装、继承、多态。前两个在 Python 中很常见,也一直再用,就不特别整理了。但是在多态这个地方就跟 Java 有点不同。我们仔细研究一下看看。

多态 Polymorphism 分为两种,编译时多态,就是函数重载啦(overload)注意与下面的 override 区别一下。还有一个是运行时多态,我们今天主要研究研究这个。
要想理解好多态,我们得先知道 emmm 很多事情,,,,让我一件一件来说。

1. 强制类型转换

首先就是 Java 中的类型转换,其实这个没啥可说的,只是需要注意一件事情,类型转换数据本身没有变化。比如下面这段代码,变量 a 一直都是一个 char 类型的变量,只是将它暂时作为 int 型的变量使用一下。

class Hello{
    public static void main(String [] args){
        char a = 'a';
        int num = a;
        System.out.print(num);
    }
}

2. 覆写

在继承关系中,子类如果定义了一个与父类方法完全相同(函数名、参数列表、返回值类型)的方法,被称为覆写(Override)。
注意与重载(Overload)进行区分,重载是指一个类中的两个方法函数名和返回值一样,但是参数列表不同。
另外:方法名相同,方法参数相同,但方法返回值不同,也是不同的方法。在Java程序中,出现这种情况,编译器会报错。

3. 程序绑定

绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。分为静态绑定和动态绑定。
直接举个动态绑定的例子吧,比如说有人结婚邀请你家去参加婚礼,但是具体谁去还不一定,有可能是你妈妈,有可能是你,有可能是你妹妹,这要看当时你们家谁有空(说不定后来你们家来了个亲戚,婚礼的时候你们都没空,就让他去了)。要是静态绑定呢,指定是谁,就必须是谁,而且编译的时候这个人必须已经存在。

比如我对于静态绑定(像 C 语言),指定使用哪个对象就是哪个对象,指定哪个属性,这个属性就必须存在。
对于动态绑定(比如 Python 支持的动态绑定),调用一个对象的方法,如果这个方法里使用到了一个属性,但是我的这个类还没有这个属性,它是在运行过程中产生的。也不用管这个属性属于哪个对象,这个属性是啥时候才有的,只要在我执行这个方法的时候这个对象里面有我想要的属性就 ok 。
Java 是一个比较折衷的语言,java 当中的方法只有 final,static,private 和构造方法是静态绑定,剩下的都是动态绑定。

4. 上转型对象

然后就是上转型对象,简单点来说,上转型对象就是对象级别的强制类型转换。这是一个 引用变量的声明类型与其实际类型不符 的例子。

将子类对象赋值给一个父类的引用类型变量,(将子类理解为一个父类使用,没有转化!!)这个父类引用所指向的对象就叫上转型对象。

上转型对象的特点:

上转型对象就是动态绑定的一个体现,比如在使用父类引用调用被子类重写的方法的时候,我不去管这个对象是哪个类的,只要里面有我要的方法就行,自然这样调用的就是被子类重写的方法。
我们先来看一个例子:

public class Area{
    public static void main(String[] args){
        Animal dog1 = new Dog();
        dog1.run();
        System.out.println(dog1.age);
    }
}

class Animal{
    public int age = 0;
    public void run(){
        System.out.println("动物跑。。。");
    }
}

class Dog extends Animal{
    public int age = 100;
    @Override
    public void run(){
        System.out.println("狗跑。。。");
    }
}
## 狗跑。。。
## 0

注意这个结果,方法可以被覆写,所以使用的是覆写之后的方法,但是属性没有覆写这一说,所以使用的就还是父类继承下来的属性。
还有在子类里面可以使用装饰器 @Override 标识一个覆写函数,这样解释器就可以帮我们检查是否真的是覆写。

不同的子类覆写的方式也不同,这样调用相同的父类方法,对于不同的子类,所得到的结果就不同,这就是多态的效果。

5. 多态

正如上文所说,多态就是 同样的行为(同一段代码)作用于不同对象时产生不同的效果。

多态想要解决的问题主要是:设计和实现的分离,这样修改设计,修改实现都非常容易。另外这样写的话代码量也会比较少,也比较容易阅读。
比如看下面这个代码:

public class TestPolymorphism{
    
    public static void main(String [] args){
        Dog dog = new Dog();
        Cat cat = new Cat();
        Bird bird = new Bird();
        dog.saySomething();
        cat.saySomething();
        bird.saySomething();
    }
}


class Dog{
    public void saySomething(){
        System.out.println("汪汪汪......");    
    }   
}

class Cat{
    public void saySomething(){
        System.out.println("喵喵喵......");    
    }   
}

class Bird{
    public void saySomething(){
        System.out.println("啾啾啾......");    
    }   
}

这个例子太经典了....
下看一下使用多态的实现

class TestPolymorphism{
    public static void animalSaySomthing(Animal an){
        an.saySomething();
    }

    public static void main(String [] args){
        Dog dog = new Dog();
        Cat cat = new Cat();
        Bird bird = new Bird();
        animalSaySomthing(dog);
        animalSaySomthing(cat);
        animalSaySomthing(bird);
    }
}

class Animal{
    public void saySomething(){}
}


class Dog extends Animal{
    public void saySomething(){
        System.out.println("汪汪汪......");
    }
}

class Cat extends Animal{
    public void saySomething(){
        System.out.println("喵喵喵......");
    }
}

class Bird extends Animal{
    public void saySomething(){
        System.out.println("啾啾啾......");
    }
}

当我们不光想要动物叫还想让他们做其他事情的时候,多态的好处就显现出来了,比如说我还想增加跑,吃,上树的方法,按照第一个的话那就需要为每一个都增加一个方法,然后每一个调用一遍,但是使用多态的话我们只需要在Animal 类中增加相应的接口,然后在子类中实现它。

额,,看到这里你一定会说这不是更麻烦了嘛,,,emmm,对于这个例子来说确实是这样,在实际生产环境中,也就是对于大型程序,多态主要是用在接口中,那个时候才能真正体现 Polymorphism 的作用。

上一篇 下一篇

猜你喜欢

热点阅读