정적 바인딩과 동적 바인딩

YaaaPyoung·2022년 4월 12일
0

바인딩(binding)이란 프로그램에 사용된 구성 요소의 실제 값 또는 프로퍼티를 결정짓는 행위를 의미합니다.

예를 들어 함수를 호출하는 부분에서 실제 함수가 위치한 메모리를 연결하는 것도 바로 바인딩입니다.

출처


1. 정적 바인딩

  • compile-time에 발생하고, Runtime 시간 동안에는 변하지 않는 상태로 유지되는 바인딩이다.
  • static, private, final 메소드는 정적 바인딩 대상이다.

아래 코드는 타입 정보를 기반으로 정적 바인딩이 발생하는 예시이다.

class Parent{}
class Child extends Parent{}
``위와 같이 부모, 자식 클래스가 있을 때``

public class StaticBindingTest{
	
	public void method(Parent p){
		System.out.println("method(Parent)...");
	}
	
	public void method(Child c){
		System.out.println("method(Child)...");
	}	
	
	public static void main(String[] args) {

		Parent parent = new Child();
		Child child = new Child();

		StaticBindingTest test = new StaticBindingTest();

		test.method(parent);
		test.method(child);
	}	
}

위처럼 오버로딩된 메소드가 있을 때 Parent 타입의 객체를 파라미터로 전달했을 때와 Child 타입의 객체를 전달했을 때, 어떤 메소드가 호출될까?

[실행결과]
method(Parent)...
method(Child)...

즉, 오버로딩된 메소드는 타입정보만을 가지고 바인딩된다. parent 참조변수의 실제 구현체가 Child 객체라고 하더라도 method(Parent p) 메소드가 호출된다.

Parent 클래스와 Child 클래스에 같은 이름의 static 메소드를 추가해보자.

class Parent{
	static void method(){
		System.out.println("parent....");
	}
}

class Child extends Parent{
	static void method(){
		System.out.println("Child...");
	}
}

public class StaticBindingTest {

	public static void main(String[] args) {
		Parent parent = new Child();
		parent.method();
	}
}

위와 같이 실행한 결과는 어떨까? Child 클래스가 method를 오버로딩했으니 Child 클래스가 재정의한 메소드가 호출될까?

[실행결과]
parent....

우선, static 메소드는 오버라이딩이 될 수 없다. 컴파일러는 static 메소드를 보고, '아 이 메소드는 오버라이딩이 불가능하니까 실제 구현 클래스가 어떤 타입이건간에 Parent 클래스의 메소드를 호출하면 되는구나'라고 생각하고 정적 바인딩을 수행하는 것이다.


2. 동적 바인딩

  • Runtime 시간에 발생하거나 변경되는 바인딩이다.

아래와 같이 Child 클래스가 Parent 클래스의 메소드를 오버라이딩하도록 코드를 작성하자.

class Parent{
	void method(){
		System.out.println("parent....");
	}
}

class Child extends Parent{
    @Override
	void method(){
		System.out.println("Child...");
	}
}

public class DynamicBindingTest {

	public static void main(String[] args) {
		Parent parent = new Child();
		parent.method();
	}
}
[실행결과]
Child...

Child 클래스는 method()를 오버라이딩했다. 참조 변수는 Parent 타입이지만 실제로는 Child 객체이므로 Child가 오버라이딩한 메소드를 호출한다. 컴파일러는 method() 를 수행하기 위해서는 실제 객체가 무엇인지 compile-time에는 판단할 수 없으므로 바인딩을 Runtime까지 미루게 된다.

3. 오버로딩 (Overloading)

  • 같은 클래스내에서 같은 이름의 메소드를 정의하고 메소드 파라미터를 다르게 전달하면서 서로 다른 로직을 수행하는 메소드를 호출할 수 있도록 한다.
  • 즉, 파라미터가 다른 경우 새로운 이름의 메소드를 정의하지 않고 기존 메소드 이름으로 같은 로직을 수행할 수 있게하는 것이다.
  • 리턴 타입은 오버로딩에 영향을 주지 않는다.
  • 오버로딩Compile-time정적 바인딩된다.

4. 오버라이딩 (Overriding)

  • 상속 관계에서 부모 클래스로부터 물려받은 메소드를 자식 클래스에서 재정의하는 것이다.
  • 부모에게 물려받은 메소드는 body가 있을 수도 없을 수도 있으나 메소드 시그니쳐는 반드시 같아야 한다.
  • 즉, 자식 클래스에서 필요에 의해 메소드 구현을 다양하게 할 수 있도록 하는 것이 목적이다.
  • 리턴 타입은 같거나 자식 클래스를 포함한 부모 타입이어야 한다.
  • 오버라이딩Runtime 시점에 바인딩되는 동적 바인딩이다.

정리하면..

정적 바인딩은 타입 정보를 활용해서 compile-time에 바인딩을 한다. 그리고 final, static, private 메소드같이 오버라이딩이 불가능한 메소드들 또한 실제 객체가 무엇인지 Runtime까지 미룰 필요가 없으므로 compile-time에 바인딩한다.

반면, 동적 바인딩은 실제 객체가 무엇인지 알아야하는 오버라이딩된 메소드를 호출할 때 발생한다.

0개의 댓글