重定义的目的在于让子类修改或者重写继承来自父类的方法。重定义的做法是:在子类中定义一个功能不同的方法(即方法体不同),但是方法的接口(即方法的声明)与父类中的某一方法完全相同。
需要注意的几点是:1)返回类型必须与父类的方法完全相同,2)访问控制必须必父类方法更公开,3)只能抛出那些父类方法声明抛出的异常。
例如:
class Employee {
String name;
int salary;
public String getDetails(){
return "Name:"+name+"\nSalary:"+salary;
}
}
public class Mannager extends Employee{
String department;
public String getDetails(){
return "Name:"+name+"\nHead of:"+department;
}
public static void main(String[] aegs){
Employee A=new Employee(); //普通生成父类的对象
Employee B=new Mannager(); //使用了向上转型规则:子类对象可以转型为父类类型的对象,反之不成立
System.out.println(A.getDetails()); //会输出name:NULL salary:0 //数据为Java的初始值
System.out.println(B.getDetails()); //会输出name:NILL Head of:NULL
}
}
父类Employee和子类Mannager中,都定义了同样的一个方法:getDetails,声明一样,就方法体不同,这就是重定义。
但是以上的System.out.println(B.getDetails);为什么输出的是Mannager的getDetails()呢?这里就涉及到一个多态的问题。Java语言运行时多态就体现在对象后面的new关键字的构造方法的调用上。由于不同的new语句,使用同样的函数调用可以自动的选择去调用哪一个类中的重定义方法。
讲这么多,你肯定听着有点不懂,因为搞得我也不知道我在讲什么了。简单一句话:重定义后,关键字new后面的类型是什么,你就会调用哪个类里面的相应重定义的方法。下面说个例子:
class Base{
Base(){
System.out.println("父类的构造方法!");
print();
}
public void print(){
System.out.println("父类的print方法!“);
}
}
class Derived extends Base{
int value;
Derived(int val){
value=val;
System.out.println("子类的构造方法!");
}
public void print(){
System.out.println("子类的print方法!with"+value);
}
}
public class Polymorphism {
public static void main(String[] args){
new Derived(123);
}
}
//数据均为Java的初始值
/*
输出以下:
父类的构造方法!
子类的print方法!with0
子类的构造方法!
*
因为new后面为Derived,所以print()调用的是Derived类的。
再来最后一个例子:
class Father{
public void func1(){
System.out.println("Father is func1");
}
public void func2(){
System.out.println("Father is func2");
}
}
class Child extends Father{
public void func1(int i){ //注意,这里的func1是重载,不是重写!
System.out.println("Child is func1");
}
public void func2(){
System.out.println("Child is func2");
}
}
public class Polymorphism2 {
public static void main(String[] arg){
Father father=new Father();
father.func1();
father.func2();
Father child=new Child();
child.func1();
child.func2();
}
}
/*
输出以下:
Father is func1
Father is func2
Father is func1
Child is func2
*/
需要注意的是,以上的子类的func1()和父类中的func1()形成一组重载的方法(参数个数不同构成重载),并不是重定义。