UFO ET IT

Java에서 호출되는 오버로드 된 메서드

ufoet 2020. 12. 25. 00:16
반응형

Java에서 호출되는 오버로드 된 메서드


수퍼 클래스에 오버로드 된 메서드가있는 기본 상속 상황이 있습니다.

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

다음 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;
    }
}

main 메소드는 단순히 Employee객체 (정적 및 동적 유형 모두) 를 생성하고 .work()이를 호출 합니다.

public static void main(String[] args){
    Employee e1 = new Employee("Manager1", 1976, "Female");
    e1.work();
}

이것은 인쇄를 끝냅니다

This person is not an Employee

이 난을 통해 찾고 정적 및 개체의 동적 유형이 모두 있기 때문에 생각했던 e1것입니다 Employee그것이 걸리는 사람의 오버로드 된 메서드를 호출 할 Employee매개 변수로합니다. 내가 이것에 대해 분명히 틀 렸기 getWorkDetail(this)때문에 Person클래스 의 줄 에있는 "this"에 대한 참조가 수퍼 클래스로 변경되어야 한다고 가정하여 디버거를 열었습니다 . 그러나 이것은 내가 찾은 것이 아닙니다.

스크린 샷

코드의이 시점에서 분명히 객체 thisEmployee객체이지만 여전히 오버로드 된 메서드를 실행하도록 선택했습니다 getWorkDetail(Person p). 누구든지이 행동을 설명 할 수 있습니까?


메서드 재정의와 달리 메서드 오버로드는 정적 형식을 기반으로 연결됩니다. 그리고이 경우 에는 유형 getWorkDetail(this)Person대해서만 알고 Person있습니다.

메서드 오버로딩은 동적 런타임 동작을 제공하도록 설계되지 않았습니다.

동적 바인딩을 활용하려면 대신 메서드를 재정의하도록 코드를 다시 디자인해야 할 수 있습니다.

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

클래스 구현을 기반으로 동작을 수정합니다. 물론 필요한 경우 오버로드 된 메서드도 재정의하는 한 메서드를 오버로드 할 수 있습니다.

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

오버로드 해결은 런타임이 아닌 컴파일 시간에 발생합니다.

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"
    }
}

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.


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

출력은 콘솔에 int로 인쇄됩니다. 이제 첫 번째 test()방법에 주석을 달고 출력이 무엇인지 확인합니다.

이것은 기본 데이터 유형에서 선호하는 계층 구조입니다. 이제 파생 유형에 대해 다음 FooChild과 같은 클래스를 선언합니다.

class FooChild extends Foo {

}

다음과 Foo같은 두 가지 새로운 방법을 만듭니다.

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

그런 다음 주요 방법에서 다음 testChild과 같이 호출 하십시오 testChild(new FooChild());.


getWorkDetail (this)은 서브 클래스가 무엇인지 모릅니다. 대신 getWorkDetail을 호출하십시오.

참조 URL : https://stackoverflow.com/questions/50014088/which-overloaded-method-is-called-in-java

반응형