Eri*_*c S 56 java inheritance overloading
我有一个基本的继承情况与超类中的重载方法.
public class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex){
name = theName;
dob = birth;
gender = sex;
}
public void work(){
getWorkDetail(this);
}
public void getWorkDetail(Employee e){
System.out.println("This person is an Employee");
}
public void getWorkDetail(Person p){
System.out.println("This person is not an Employee");
}
}
Run Code Online (Sandbox Code Playgroud)
以下Employee类扩展了Person上面的类:
public class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex){
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
}
Run Code Online (Sandbox Code Playgroud)
main方法只是创建一个Employee对象(静态和动态类型)并调用.work()它:
public static void main(String[] args){
Employee e1 = new Employee("Manager1", 1976, "Female");
e1.work();
}
Run Code Online (Sandbox Code Playgroud)
这最终打印
This person is not an Employee
期待通过这个我想,既然静态和动态类型的对象e1是Employee它会调用亲自重载方法接受一个Employee作为参数.因为我对此明显错误,所以我打开了一个调试器,假设getWorkDetail(this)在Person类中的行中对"this"的引用必须已经变形为它的超类.然而,这不是我发现的.
显然,代码this中的这一点是一个Employee对象,但它仍然选择执行重载方法getWorkDetail(Person p).谁能解释这种行为?
ern*_*t_k 70
与方法覆盖不同,方法重载基于静态类型链接.在这种情况下,getWorkDetail(this)在Person只知道的Person类型.
方法重载不是为了提供动态运行时行为而设计的.
要利用动态绑定,您可能需要重新设计代码以覆盖方法,而不是:
public static void main(String[] args) throws IOException {
new Employee("Manager1", 1976, "Female").getWorkDetail();
new Person("Manager1", 1976, "Female").getWorkDetail();
}
Run Code Online (Sandbox Code Playgroud)
并根据实现类修改行为.当然,您可以重载方法,只要您负责覆盖重载方法,如果需要的话.
class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex) {
name = theName;
dob = birth;
gender = sex;
}
public void getWorkDetail() {
System.out.println("This person is not an Employee");
}
}
class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex) {
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
public void getWorkDetail() {
System.out.println("This person is an Employee");
}
}
Run Code Online (Sandbox Code Playgroud)
Cod*_*der 23
重载解析在编译期间发生,而不是在运行时.
因此,当您调用时getWorkDetails(this),this假定为Person(它是静态类型),因此称为相应的重载.
注意:使用this内部Employee类会使它成为一种Employee类型.您可以通过重载验证这一点work()在Employee这样的.
class Employee extends Person {
...
public void work() {
getWorkDetails(this); // This should print "This person is an Employee"
}
}
Run Code Online (Sandbox Code Playgroud)
在某些语言中,参数被解析为其动态类型,但不是在java中.编译器已经在编译时确定了您的getWorkDetail(this);意愿.this属于类型Person,因此getWorkDetail(Person e)被称为.在您的具体情况下,解决方案非常明显.正如其他人已经指出的那样,你需要getWorkDetail()在Employee课堂上重写.
要解决在运行时解析参数类型的一般问题,instanceof应避免使用运算符,因为它通常会导致不干净的代码.
如果您有两个不同的类,则无法再实现上述简单的解决方案.在这些情况下,您将不得不使用访问者模式.
考虑以下类:
public interface Animal {
default void eat(Food food) {
food.eatenBy(this);
}
void eatMeat(Meat meat);
void eatVegetables(Vegetables vegetables);
}
public class Shark implements Animal {
public void eatMeat (Meat food) {
System.out.println("Tasty meat!");
}
public void eatVegetables (Vegetables food) {
System.out.println("Yuck!");
}
}
public interface Food {
void eatenBy(Animal animal);
}
public class Meat implements Food {
public void eatenBy(Animal animal) {
animal.eatMeat(this);
}
}
public class Vegetables implements Food {
public void eatenBy(Animal animal) {
animal.eatVegetables(this);
}
}
Run Code Online (Sandbox Code Playgroud)
你可以这样打电话:
Animal animal = new Shark();
Food someMeat = new Meat();
Food someVegetables= new Vegetables();
animal.eat(someMeat); // prints "Tasty meat!"
animal.eat(someVegetables); // prints "Yuck!"
Run Code Online (Sandbox Code Playgroud)
跟随访问者模式调用Animal.eat将调用Food.eatenBy,这由两者Meat和Vegetables.实现.这些类将调用更具体eatMeat或eatVegetables方法,它使用正确的(动态)类型.