상속과 다형성 - 동적 바인딩과 정적 바인딩

동적 바인딩과 정적 바인딩

정적 바인딩(Static Binding)

  • 컴파일타임(Compile Time)에 선언된 객체의 타입에 따라 호출될 메서드를 인식
  • 자바의 멤버 변수는 정적 바인딩이 적용되므로 다형성 특징을 이용하지 못함.

    • 선언된 타입의 멤버 변수 접근
  • 자바의 클래스 메서드(static method) 역시 정적 바인딩이 적용되므로 다형성 특징을 이용하지 못함.

    • 오버라이딩된 자식의 메서드를 호출하는 것이 아니라 각각의 클래스에 별개의 메서드가 존재하는 것

동적 바인딩(Dynamic Binding)

  • 런타임(Run Time)에 실제 생성된 객체 타입에 따라 호출될 메서드를 인식
  • 자바의 인스턴스 메서드(non-static method)는 동적 바인딩이 적용되므로 다형성의 특징을 적극 이용

    • 자식의 클래스에서 부모의 인스턴스 메서드를 오버라이딩(재정의)한 경우, 부모 타입의 참조 변수라고 할지라도 자식 타입의 객체를 생성했다면 자식의 메서드를 호출

메서드 Overridng과 Hiding

메서드 Overridng

  • 동적 바인딩이 적용되는 상황
  • 자식 클래스에서 부모 메서드를 재정의한 경우 동적 바인딩에 의해 자식의 메서드를 호출
Java
class Employee {
    String skill = "Work Hard";

    public void getSkill() {
        System.out.println("직원 스킬 : " + skill);
    }
}

class Engineer extends Employee {
    String skill = "Play Hard";

    public Engineer(String skill) {
        this.skill = skill;
    }

    // 메서드 오버라이딩(동적 바인딩 적용)
    @Override
    public void getSkill() {
        System.out.prinln("개발자 스킬 : " + skill);
    }
}

public class SkillTest {
    public static void main(String[] args) {
        Employee emeg = new Engineer();

        emeg.getSkill();    // 동적 바인딩(런타임 시 오버라이딩 된 자식 객체 메서드 호출)
        System.out.println("emeg의 스킬 : " + emeg.skill);     // 정적 바인딩(참조 변수 타입인 부모의 변수 접근)
    }
}
개발자 스킬 : Play Hard     // 인스턴스 메서드는 동적 바인딩
emeg의 스킬 : Work Hard    // 멤버 변수는 정적 바인딩

Hiding

  • 정적 바인딩이 적용되는 상황
  • 자식 클래스에서 부모 클래스의 static 메서드와 똑같은 static 메서드를 정의한 경우
  • static 메서드(클래스 메서드)가 오버라이딩이 된 것이 아니라 메서드가 2개 생긴 셈
  • 따라서 자식 클래스에서 부모 클래스의 메서드를 숨긴 효과
Java
class Employee {
    static String skill = "Work Hard";

    public static void getSkill() {
        System.out.println("직원 스킬 : " + skill);
    }
}

class Engineer extends Employee {
    static String skill = "Play Hard";

    public Engineer(String skill) {
        this.skill = skill;
    }

    // 메서드 Hiding(정적 바인딩 적용)
    // @Override  오버라이딩 annotation 작성 불가
    public static void getSkill() {
        System.out.prinln("개발자 스킬 : " + skill);
    }

    // 컴파일 에러 : 부모의 static은 자식이 인스턴스 메서드로 오버라이딩 불가능
    /*
    public void getSkill() {
        System.out.prinln("개발자 스킬 : " + skill);
    }
    */
}

public class SkillTest {
    public static void main(String[] args) {
        Employee emeg = new Engineer();

        emeg.getSkill();    // 정적 바인딩(컴파일 시 참조 변수의 타입인 부모의 메서드 호출)
        System.out.println("emeg의 스킬 : " + emeg.skill);     // 정적 바인딩(참조 변수 타입인 부모의 변수 접근)
    }
}
직원 스킬 : Work Hard     // 클래스 메서드(static method)는 정적 바인딩
emeg의 스킬 : Work Hard    // 멤버 변수는 정적 바인딩