Java是一种面向对象的编程语言,面向对象的三大特性就是继承,封装,多态。下面细细说一说多态。
多态的定义:一个事物的多种形态,指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
有多态往往有动态绑定,动态绑定详见:http://blog.csdn.net/qq_38663729/article/details/78023479
复杂说用户创建了一个引用变量,在程序编译的时候无法判断出到底调用哪个类中的方法,当程序在编译期,虚拟机根据创建的对象判断这个引用指向的是哪个类的对象,用户在不需要修改代码的情况下,可以实现一个方法的不同实现,实现一个事物的不同表现。把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
多态的实现有三个条件:继承,重写,父类引用指向子类对象(向上转型)
继承好理解,重写是当存在继承关系的时候,父类的方法不能满足子类的需要,或者不符合子类的特点,我们就需要对其进行重写,让他表现出自己的特点(这里面说的所有都是对方法来说的)。父类引用指向子类对象也叫向上转型,我们声明一个父类的引用,当我们要创建对象的时候其实创建的是子类的对象。只有满足了这三个条件我们才能在代码中对同一特点用不同行为实现。
多态遵循着当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
多态的好处:
1.可替换性(substitutability):对一个类的行为有不同的表现形式,例如动物的叫声有不同的表现,汪汪,喵喵……
2.可扩充性(extensibility):多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability):多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.灵活性(flexibility):它在应用中体现了灵活多样的操作,提高了使用效率。我们可以灵活的调用方法
5.简化性(simplicity):提高了代码的复用性,简化了代码的书写。
多态的实现形式有说三种有说两种的,更偏爱三种:通过继承实现方法重写,方法重载,接口的实现。两种中没有方法的重载。
父类 引用=new 子类
接口 引用=new 接口实现类
下面我们举一个最最普通的例子,动物都有叫声,这是动物这个大类的行为,但是每种动物的叫声是不一样的,这是各个具体类的行为。我们首先通过继承实现重写
package demo_3; public class Test {
public static void main(String[] args) {
Animal c = new Cat();
c.voice();
Animal d = new Dog();
d.voice();
}
} class Cat extends Animal {
public void voice() {
System.out.println("喵喵");
}
} class Dog extends Animal {
public void voice() {
System.out.println("汪汪");
}
} class Animal{
public void voice() {
System.out.println("动物叫");
}
}
输出:
喵喵
汪汪
上面的代码中Cat和Dog类通过继承Animal类获取到子类中的方法,通过重写对方法进行重新定义
下面通过接口实现重写,接口中定义一个方法,接口中只有抽象的方法,写几个实现这个接口的类
package demo_2; public interface Animal {
public abstract void voice();
}
package demo_2; public class Test {
public static void main(String[] args) {
Animal c = new Cat();
c.voice();
Animal d = new Dog();
d.voice();
}
} class Cat implements Animal {
@Override
public void voice() {
System.out.println("喵喵");
}
} class Dog implements Animal {
@Override
public void voice() {
System.out.println("汪汪");
}
}
输出:
喵喵
汪汪
上面提到过对于重写只是对方法来说的,对属性无法进行重写
package demo_2; public class T extends A {
public String name = "子类属性";
public static void main(String[] args) {
A a = new T();
System.out.println(a.name);
}
}
class A{
public String name = "父类属性";
}