Which Overloaded Method is Called in Java

后端 未结 5 564
一向
一向 2021-01-30 12:56

I have a basic inheritance situation with an overloaded method in the super class.

public class Person {
    private String name;
    private int dob;
    priva         


        
相关标签:
5条回答
  • 2021-01-30 13:10

    Call preference

    class Foo {
        static void test(int arg) { System.out.println("int"); }
        static void test(float arg) { System.out.println("float"); }
        static void test(Integer arg) { System.out.println("Integer"); }
        static void test(int... arg) { System.out.println("int..."); }
    
        public static void main(String[] arg) {
            test(6);
        }
    }
    

    The output will be int printed on console. Now you comment the first test() method and see what is the output coming.

    This is the preference hirarchey in primitive data types. Now coming to derived types declare a class FooChild like this

    class FooChild extends Foo {
    
    }
    

    and create two new methods in Foo like

    static void testChild(Foo foo) { System.out.println("Foo"); }
    static void testChild(FooChild fooChild) { System.out.println("FooChild"); }
    

    then in main method try calling testChild like this testChild(new FooChild());.

    0 讨论(0)
  • 2021-01-30 13:11

    getWorkDetail(this) does not know what the subclasses are. call getWorkDetail instead.

    0 讨论(0)
  • 2021-01-30 13:23

    Unlike method overrides, method overloads are linked based on the static type. And in this case, getWorkDetail(this) in Person only knows about the Person type.

    Method overloading is not designed to provide dynamic runtime behavior.

    To take advantage of dynamic binding, you may need to redesign your code to override the methods, instead:

    public static void main(String[] args) throws IOException {
        new Employee("Manager1", 1976, "Female").getWorkDetail();
        new Person("Manager1", 1976, "Female").getWorkDetail();
    }
    

    And modify behavior based on implementing classes. Of course, you can overload methods, as long as you take care of overriding the overloaded methods too, if required.

    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");
        }
    }
    
    0 讨论(0)
  • 2021-01-30 13:26

    The overload resolution happens during compile time, not at runtime.

    So, when you call getWorkDetails(this), this is assumed to be a Person (which is the static type) and hence called the corresponding overload.

    Note: Using this inside Employee class would have made it an Employee type. You can verify this by overloading work() in Employee like this.

    class Employee extends Person {
        ...
    
        public void work() {
            getWorkDetails(this); // This should print "This person is an Employee"
        }
    }
    
    0 讨论(0)
  • 2021-01-30 13:27

    Problem specific solution

    In some languages parameters are resolved to their dynamic type, but not in java. The compiler already determines at compile time where your getWorkDetail(this); will go. this is of type Person, so getWorkDetail(Person e) is called. In your specific case the solution is quite obvious. As others have already pointed out, you'll need to override getWorkDetail() in the Employee class.

    Resolving methods to their dynamic parameter types

    To solve the general problem of resolving parameter types at runtime, using the instanceof operator should be avoided, as it usually leads to unclean code.

    If you have two different classes, a solution as simple as stated above is no longer possible. In these cases you'll have to use the visitor pattern.

    Consider the following classes:

    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);
        }
    }
    

    Which you can call like this:

    Animal animal = new Shark();
    Food someMeat = new Meat();
    Food someVegetables= new Vegetables();
    animal.eat(someMeat);        // prints "Tasty meat!"
    animal.eat(someVegetables);  // prints "Yuck!"
    

    Following the visitor pattern calling Animal.eat will call Food.eatenBy, which is implemented by both Meat and Vegetables. Those classes will call the more specific eatMeat or eatVegetables method, which uses the correct (dynamic) types.

    0 讨论(0)
提交回复
热议问题