|
java基础 - 方法的覆盖和重载
Java 私塾跟我学系列——JAVA 篇 网址:www.javass.cn
1:方法的覆盖
1.1:什么是方法的覆盖(Overridden Methods)
在类继承中,子类可以修改从父类继承来的行为,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的:名称、返回类型、参数列表。
如果在新类中定义一个方法,其名称、返回类型及参数表正好与父类中方法的名称、返回类型及参数相匹配,那么,新方法被称做覆盖旧方法。
1.2:示例
如下在 Employee 和 Manager 类中的这些方法:
- public class Employee {
- String name;
- int salary;
- public String getDetails() {
- return " Name: " + name + " \n " + "Salary: " + salary;
- }
- }
- public class Manager extends Employee {
- String department;
- public String getDetails() {
- return " Name: " + name + " \n " + " Manager of " + department;
- }
- }
复制代码 Manager 类有一个定义的 getDetails()方法,因为它是从 Employee 类中继承的。基本的方法被子类的版本所代替或覆盖了。
1.3:到底运行哪一个方法?
这里会给我们带来一个麻烦,父子类中有相同的方法,那么在运行时到底调用哪一个方法呢?假设下述方案:
Employee e = new Employee();
Manager m = new Manager();
如果请求 e.getDetails()和 m.getDetails(),就会调用不同的行为。Employee 对象将执行 与 Employee 有 关的 getDetails 版本, Manager 对 象将执行 与 Manager 有关的getDetails()版本。
不明显的是如下所示:
Employee e = new Manager();
e.getDetails();
或某些相似效果,比如一个通用方法参数或一个来自异类集合的项。
事实上,你得到与变量的运行时类型(即,变量所引用的对象的类型)相关的行为,而不是与变量的编译时类型相关的行为。这是面向对象语言的一个重要特征。它也是多态性的一个特征,并通常被称作虚拟方法调用。
在前例中,被执行的 e.getDetails()方法来自对象的真实类型,Manager。
因此规则是:编译时看数据类型,运行时看实际的对象类型(new 操作符后跟的构造方法是哪个类的)。一句话:new 谁就调用谁的方法。
1.4:覆盖方法的规则
记住,子类的方法的名称以及子类方法参数的顺序必须与父类中的方法的名称以及参数的顺序相同,以便该方法覆盖父类版本。下述规则适用于覆盖方法:
(1):覆盖方法的返回类型、方法名称、参数列表必须与它所覆盖的方法的相同。
(2):覆盖方法不能比它所覆盖的方法访问性差(即访问权限不允许缩小)。
(3):覆盖方法不能比它所覆盖的方法抛出更多的异常。
这些规则源自多态性的属性和 Java 编程语言必须保证“类型安全”的需要。考虑一下这个无效方案:
- public class Parent {
- public void method() {
- }
- }
- public class Child extends Parent {
- private void method() {//编译就会出错
- }
- }
- public class Test{
- public void otherMethod() {
- Parent p1 = new Parent();
- Parent p2 = new Child();
- p1.method();
- p2.method();
- }
- }
复制代码 Java 编程语言语义规定,p2.method()导致方法的 Child 版本被执行,但因为方法被声明为 private,p2(声明为 Parent)不能访问它。于是,语言语义冲突。
2:方法的重载
假如你必须在不同情况下发送不同的信息给同一个成员方法的话,该怎么办呢?你可以通过对此成员方法说明多个版本的方法来实现重载。重载的本质是创建了一个新的成员方法:你只需给它一个不同的参数列表。
2.1:什么是重载
在同一个 Java 类中(包含父类),如果出现了方法名称相同,而参数列表不同的情况就叫做重载。
参数列表不同的情况包括:个数不同、类型不同、顺序不同等等。特别提示,仅仅参数变量名称不同是不可以的。
2.2:重载示例
如下例所示:
void getArea(int w,int h);
void getArea(float w,float h);
在第二种情况下,成员方法 getArea()接受两个浮点变量作为它的参数,编译器根据调用时的不同参数来决定该调用哪一种成员方法,假如你把两个整数提供给成员方法,就调用第一个成员方法;假如你把两个浮点数提供给成员方法,第二个成员方法就被调用。
当写代码来调用这些方法中的一个方法时,便以其会根据提供的参数的类型来选择合适的方法。
注意:跟成员方法一样,构造方法也可以重载。
2.2:方法的重载的规则
(1):方法名称必须相同
(2):参数列表必须不同(个数不同,或类型不同,或参数排列顺序不同)。
(3):方法的返回类型可以相同也可以不相同。仅仅返回类型不同不足以成为方法的重载。
注意:调用语句的参数表必须有足够的不同,以至于允许区分出正确的方法被调用。正常的拓展晋升(如,单精度类型 float 到双精度类型 double)可能被应用,但是这样会导致在某些条件下的混淆。
2.3:比较方法的覆盖和重载
重载方法:
在一个类(或父子类)中用相同的名字创建多个方法(每个方法的参数表不同)。
方法覆盖:
在一个类中创建的方法与父类中方法的名字、返回类型和参数表相同,覆盖是针对两个类说的,而且必须是子类(或孙类,孙孙类等)覆盖掉父类的方法。
|
|