1多态性( Polymorphism)
1.1 多态性的概念
多态性是面向对象方法的三个重要特性之一。多态是指在一个程序中相同的名字可以表示不同的实现。 Java 的多态性主要表现在三个方面,①方法重载:指可在一个类中定义多个名字相同而实现不同的成员方法,它是一种静态多态性,或称编译时多态;②方法覆盖(重写),即子类可以隐藏与父类中的同名成员方法,它是一种动态多态性,或称运行时多态;③变量覆盖,即子类可以隐藏与父类中的同名成员变量。多态性大大提高程序的抽象性和简洁性。从静态与动态的角度可将多态分为编译时多态(静态多态)和运行时多态(动态多态)。
1.编译时多态(静态多态)
编译时多态是指在编译阶段,编译器根据实参的不同来静态确定具体调用相应的方法,Java 中的方法重载属于静态多态。
2.运行时多态(动态多态)
运行时多态是指运行时系统能根据对象状态不同来调用其相应的成员方法,即动态绑定。Java 中的方法覆盖属于动态多态。
由于子类继承了父类的非私有属性,所以子类对象可以作为父类对象使用(即上转型对象)。程序中凡是使用父类对象的地方,都可以用子类对象来代替。可以通过引用子类的实例来调用子类的方法。
1.2 方法重载( Method Overloading)
方法重载是指 Java 的同一个类中的两个或两个以上的方法可以使用同一个名字,而它们的参数声明(个数、类型和顺序)不同。
例如: add( )方法可能有以下三个版本:
public int add(int x, int y) {
return x + y;
}
public double add(double x, double y) {// 参数类型不同重载
return x + y;
}
public double add(double x, double y, double z) {// 参数个数不同重载
return x + y + z;
}
重载方法并存于程序中,当一个重载方法被调用时, javac 编译器会根据实参的个数、类型和顺序来表明实际调用的重载方法的版本。因此,每个重载方法的参数个数、类型和顺序必须是不同的。虽然每个重载方法可以有不同的返回类型,但返回类型并不足以区分所使用的是哪个方法。方法重载属于 Java的静态多态,当 Java 在编译阶段调用一个重载方法时,形参与调用实参匹配的方法才被调用。
方法重载的目的不是代码复用,它可以提高成员方法的抽象程度,对外提供一致简洁的使用接口。
1.3 方法覆盖( Method Override)
方法覆盖是指子类对父类中相同方法头的方法的重新定义,又称为方法重写。 这时子类和父类具有方法头(包括修饰符、方法名、参数表和返回值类型)相同,但方法体不同的同名方法。
方法重写的原则是:①改写后的方法不能比被重写的方法有更严格的访问权限。②改写后的方法不能比被重写的方法产生更多的异常。
调用重写方法的原则是:①对子类的一个实例,若子类重写了父类的方法,则运行时系统调用子类的方法;②对子类的一个实例,若子类继承了父类的方法(未重写),则运行时系统调用父类的方法。
调用重写方法的格式是:①一般地,在子类中通过“方法名”所调用的成员方法包括子类中的重写方法、继承自父类的方法(未重写)和子类新增的方法这三种。②若要访问父类中被覆盖的成员方法,则必须使用 super 关键字来表示父类对象,其一般调用格式是:
super.<方法名>([实参表]);
通过方法覆盖,可以在子类中修改父类中同名方法的功能。方法覆盖实现了在运行时的多态性,通过运行时的对象状态来调用其相应的成员方法,从而提高程序的简洁性和灵活性。
方法覆盖与方法重载的异同:( 1)相同点:①二者都要求方法名相同;②二者都可以用于抽象方法和非抽象方法。( 2)不同点:①方法覆盖要求参数签名必须一致,而方法重载要求参数签名必须不一致;②方法覆盖只能用于子类覆盖父类的方法,方法重载用于同一个类的所有方法(包括从父类中继承而来的方法);③方法覆盖对方法的访问权限和抛出的异常有
特殊的要求,而方法重载在这方面没有任何限制;④方法覆盖要求返回类型必须一致,而方法重载对此不做限制;⑤父类的一个方法只能被子类覆盖一次,而一个方法在所在的类中可以被重载多次。
1.4 变量覆盖( Variable Override)
变量覆盖是指在子类中对从父类继承过来的成员变量重新定义,即变量名相同而其类型相同或不同,又称为成员变量的隐藏。
成员变量覆盖的处理规则是:①在子类中将继承父类的同名变量“隐藏”了。 ②若子类执行继承父类的操作,则使用继承自父类的变量;若子类执行自己定义的操作时,则使用自己定义的变量。
若在子类中引用父类中继承的变量,则可使用 super 关键字来表示父类对象,其一般格式是:
super.<父类变量名> ;