초기 및 후기 바인딩이란 무엇입니까?


77

나는 초기와 늦게 구속되는 것에 대해 계속 들었지만, 그것이 무엇인지 이해하지 못한다. 이해하지 못하는 다음 설명을 발견했습니다.

초기 바인딩은 디자인 타임 동안 변수에 값을 할당하는 것을 말하고, 늦은 바인딩은 런타임 동안 변수에 값을 할당하는 것을 말합니다.

누군가 두 가지 유형의 바인딩을 정의하고 비교할 수 있습니까?


1
컴파일 시간과 런타임.
barlop

다음 주제에 대해 잘 읽어보십시오 : en.wikibooks.org/wiki/Introduction_to_Programming_Languages/…
Jay Elston

답변:


84

혼동에는 바인딩과로드라는 두 가지 주요 개념이 있습니다. 그것은 종종 둘 다를 수행하는 중간의 어딘가에있는 DataBinding의 개념에 의해 혼란 스럽습니다. 그것을 고려한 후, 나는 trifecta를 완성하기 위해 개념을 하나 더 추가 할 것입니다.

종류

후기 바인딩 : 런타임 동안 변수가 실행될 때까지 유형을 알 수 없습니다 . 일반적으로 할당을 통해 유형을 강제하는 다른 방법이 있습니다. 동적으로 유형이 지정된 언어는이를 기본 기능이라고하지만 많은 정적으로 유형이 지정된 언어에는 늦은 바인딩을 수행하는 방법이 있습니다

[특수] 동적 유형, 내부 검사 / 반사, 플래그 및 컴파일러 옵션을 사용하거나 동적 디스패치를 ​​빌리고 확장하여 가상 메소드를 통해 자주 구현

Early Binding : 런타임에 변수가 실행되기 전에 일반적으로 정적, 선언적 수단을 통해 유형이 알려져 있습니다.

표준 기본 유형을 사용하여 자주 구현

기능

정적 디스패치 : 컴파일시 알려진 특정 기능 또는 서브 루틴; 모호하지 않으며 서명과 일치합니다.

정적 함수로 구현됩니다. 어떤 메소드도 같은 서명을 가질 수 없습니다

동적 디스패치 : 컴파일시 특정 함수 또는 서브 루틴이 아닙니다 . 실행하는 동안 컨텍스트에 의해 결정됩니다. "동적 디스패치"에 대한 두 가지 접근 방식이 있으며, 적절한 컨텍스트 구현을 선택하기 위해 어떤 상황 정보가 사용되는지에 의해 구별됩니다.

에서는 단일 [ 동적 ] 디스패치 인스턴스의 유형은 적절한 기능 구현을 결정하는 데 사용된다. 정적 타입 언어에서, 이것이 실제로 의미하는 것은 인스턴스 타입이 변수가 선언 / 할당 될 때 표시되는 참조 타입에 관계없이 어떤 메소드 구현이 사용될지를 결정한다는 것입니다. 적절한 구현을 유추하는 데 단일 유형 (객체 인스턴스 유형) 만 사용되므로이 방법을 "단일 디스패치"라고합니다.

도있다 여러 [ 동적 ] 디스패치 입력 파라미터 유형이 또한 호출하는 기능 구현 결정할 수. 인스턴스 유형 매개 변수 유형 모두와 같은 여러 유형 이 선택된 메소드 구현에 영향을주기 때문에이 접근 방식을 "다중 디스패치"라고합니다.

가상 또는 추상 기능으로 구현됩니다. 다른 단서는 재정의, 숨겨진 또는 음영 처리 된 방법을 포함합니다.

주의 : 메소드 오버로딩에 동적 디스패치가 관련되는지 여부는 언어마다 다릅니다. 예를 들어, Java에서는 오버로드 된 메소드가 정적으로 전달됩니다.

가치

지연로드 : 필요할 때까지 값 할당지연 시키는 객체 초기화 전략 . 객체가 본질적으로 유효하지만 의도적으로 불완전한 상태에있게하고 데이터를로드하기 전에 데이터가 필요할 때까지 기다립니다. 대용량 데이터 세트를로드하거나 외부 리소스를 기다리는 데 특히 유용합니다.

일부 다운 스트림 호출자가 해당 컬렉션의 내용 (예 : get_value_at, get_all_as 등)을 볼 때까지 생성자 또는 초기화 호출 중에 컬렉션 또는 목록을 복합 객체로 의도적으로로드하지 않음으로써 종종 구현됩니다. 변형에는 컬렉션에 대한 메타 정보 (크기 또는 키와 같은)를로드하지만 실제 데이터는 생략합니다. 또한 개발자에게 상당히 안전하고 효율적인 싱글 톤 구현 체계를 제공하기 위해 일부 런타임에 메커니즘을 제공합니다.

Eager Loading : 유효한 상태에 있다고 생각하기 전에 모든 데이터를 완성하기 위해 모든 값 할당즉시 수행 하는 객체 초기화 전략 .

생성자 호출 또는 초기화와 같이 가능한 한 빨리 알려진 모든 데이터가있는 복합 객체를 제공하여 자주 구현

데이터 바인딩 : 종종 두 개의 호환 가능한 정보 스트림 사이에 활성 링크 또는 맵을 작성하여 하나의 변경 사항이 다른 변경 사항으로 다시 반영되고 그 반대의 경우도 마찬가지입니다. 호환 되려면 종종 공통 기본 유형 또는 인터페이스가 있어야합니다

서로 다른 애플리케이션 측면 (예 : 뷰-뷰-뷰, 모델-컨트롤러 등)간에 깨끗하고 일관된 동기화를 제공하고 소스 및 대상, 엔드 포인트, 바인드 / 바인드 해제, 업데이트 및 이벤트와 같은 개념에 대해 이야기하기 위해 종종 구현됩니다. on_bind, on_property_change, on_explicit, on_out_of_scope


편집 참고 : 이러한 문제가 자주 발생하는 예에 대한 설명을 제공하는 마지막 주요 편집입니다. 특정 코드 예제는 전적으로 구현 / 런타임 / 플랫폼에 의존합니다


2
이 답변은 객체 지향 언어에 너무 구체적으로 보입니다.
Jack

27

컴파일하는 동안 컴파일러가 결정한 것은 EARLY / COMPILE TIME Binding을 참조 할 수 있으며 RUNTIME 에서 결정되는 것을 LATE / RUNTIME 바인딩 이라고 합니다.

예를 들어

메서드 오버로드 및 메서드 재정의 .

1) Method Overloading 에서 메소드에 대한 메소드 호출은 컴파일 할 때 컴파일러가 어떤 함수를 호출할지 결정한다는 의미에서 컴파일러에 의해 결정됩니다. 따라서 초기 바인딩 되고 있습니다.

2) 메서드 재정의에서 RUNTIME에 어떤 메서드를 호출할지 결정됩니다. 그래서 그것은 늦은 바인딩으로 나타납니다 .

간단하고 쉽게 사용할 수 있도록 노력했습니다. 도움이 되었기를 바랍니다.


9

늦은 바인딩은 런타임에 동작이 평가 될 때입니다. 실제로 프로그램이 실행 중일 때만 가지고있는 정보를 기반으로 행동 방법을 결정하고 싶을 때 필요합니다. 내 생각에 가장 명확한 예는 가상 함수 메커니즘, 특히 C ++입니다.

class A
{
public:
    void f() {}
    virtual void g() {}
};

class B : public A
{
    void f() {}
    virtual void g() {}
};

int main()
{
    A* a = new B;
    a->f();
    a->g();
}

이 예에서, a->f()실제로 호출 void A::f()조기 (또는 정적) 바인딩 등 런타임에 프로그램이기 때문에, 생각 그것이 단지 포인터입니다 A반면, 형태 변수 a->g()실제로 호출 void B::g()컴파일러는, 보는이 있기 때문에, g()가상이다, 보는 코드를 삽입 런타임에 호출 할 올바른 함수의 주소를 올립니다.


1
"런타임"? C ++에 대해 이야기하고 있습니다. C ++은 머신 코드로 직접 컴파일되므로 가상 메소드를 분석하기 위해 런타임이 필요하지 않습니다.
tdammers

3
@tdammers C ++에는 실제로 가상 호출이 아닌 런타임 라이브러리가 필요합니다. 주의 깊게 읽는다면,이 대답은 컴파일러 말하는 것을 알 수 있습니다 "올바른 기능을 [...]의 주소를 조회하는 코드를 삽입 에서 실행".

그러나 "올바른 함수의 주소를 찾는 코드"는 기본적으로 형식에 구애받지 않는 2 단계 포인터 역 참조와 함수 호출입니다. "생각"은 없습니다. 그것이 안정적으로 작동하는 유일한 이유는 컴파일러가 컴파일 타임에 타입 검사 를하기 때문입니다 . 런타임에 생성 된 코드는 컴파일러가 형식 확인 과제를 수행했음을 신뢰합니다. 안전하지 않은 캐스트 (예 : C 스타일 포인터 캐스트)를 사용 하는 경우 C ++ 객체를 잘못된 클래스의 객체로 합법적으로 취급 할 있지만 vtables가 완전히 엉망이되어 코드가 중단됩니다.
tdammers

@tdammers 나는 컴파일러의 구현 세부 사항이므로 일부 난해한 컴파일러에게는 맞지 않을 수도 있기 때문에 그런 종류의 대답을 피하려고했습니다. 중요한 것은 개념입니다.
얌 마르코비치

1
@tdammers 그리고 "런타임"이란 "런타임에 프로그램"을 의미합니다. 분명히 C ++은 관리되지 않습니다. 그러나 당신이 나에게 혼란을 일으킬 수 있음을 보여 주었으므로 나는 그것을 전체 문구로 바꾸고 있습니다.
얌 마르코비치

5

함수 포인터에 익숙하다면 이것이 예일 것입니다. 정의 된 함수는 초기 바인딩이라고 할 수 있습니다. 반면 함수 포인터를 사용하면 바인딩이 늦습니다.

  int add(int x,int y)
  {
    return x+y;
  }
  int sub(int x,int y)
  {
      return x-y;
  }


    int main()
    {
     //get user choice
     int(*fp)(int,int);
     //if add
      fp=add;
     //else if sub
     fp=sub;
     cout<<fp(2,2);
    }

여기에 함수 add와 sub는 함수입니다 (주소는 컴파일 타임 링커에서 바인딩됩니다)

그러나 함수 포인터는 늦게 바인딩됩니다. fp는 사용자 선택에 따라 add 또는 sub를 호출 할 수 있습니다 [런타임].


3

초기 및 후기 바인딩은 유형의 컨텍스트에서만 의미가 있으며 설명하는 방식이 아닙니다. 거의 모든 현대 언어는 모든 값에 고정 유형이 있다는 의미에서 입력됩니다. 우리가 동적 언어와 정적 형식의 언어를 볼 때 차이점이 있습니다. 동적으로 유형이 지정된 언어에서 변수에는 유형이 없으므로 모든 유형의 값을 참조 할 수 있으며 이는 일부 변수가 참조하는 객체에서 메소드를 호출 할 때 해당 호출이 유효한지 여부를 판별하는 유일한 방법임을 의미합니다. 객체의 클래스를 찾아 해당 메소드가 실제로 존재하는지 확인하십시오. 이것은 실제 메소드 검색이 마지막 순간까지 연기되기 때문에 런타임에 클래스에 새로운 메소드를 추가하는 것과 같은 멋진 것들을 허용합니다. 대부분의 사람들은이 상황을 늦게 구속한다고합니다.

정적으로 유형이 지정된 언어 변수에는 유형이 있으며 한 번 선언되면 동일한 유형이 아닌 값을 참조 할 수 없습니다. 이것은 사실이 아니지만 현재로서는 가정 해 보겠습니다. 이제 변수가 특정 유형의 값만 참조한다는 것을 알고 있다면 코드가 실행되기 전에 유효성을 확인할 수 있기 때문에 메소드 호출이 런타임인지 아닌지를 알아낼 이유가 없습니다. 이것을 초기 바인딩이라고합니다.

루비에서 늦은 바인딩을 보여주는 예제 :

a = 1 # a is an integer at this point
a.succ # asking for its successor is valid

class A
  def method_a
    # some code
  end
end

a = A.new
a.method_a # this is also valid
a.succ # this is not valid


class A # we can re-open the class and add a method
  def succ
    # some more code
  end
end
a.succ # now this is valid

모든 유형이 런타임에 고정 된 Java와 같은 언어에서는 위의 일련의 동작이 불가능합니다.


1

학문적 정의를 제공하는 대신 VBA를 사용하는 실제 예를 사용하여 차이점을 보여 드리겠습니다.

초기 바인딩 :

Dim x As FileSystemObject
Set x = New FileSystemObject
Debug.Print x.GetSpecialFolder(0)

디자인 타임에 "Microsoft 스크립팅 런타임"구성 요소에 대한 참조를 설정해야합니다 . 오타가 FileSystemObject있거나 메소드 이름이 같은 경우 컴파일 타임에 이미 오류 메시지가 표시되는 이점이 있습니다 GetSpecialFolder.

늦은 바인딩

Dim x As Object
Set x = CreateObject("Scripting.FileSystemObject")
Debug.Print x.GetSpecialFolder(0)

이를 위해서는 사전에 참조를 설정하지 않아도되며 인스턴스 생성 및 유형 결정은 런타임에 발생합니다. 존재하지 않는의 메소드를 호출하려고 할 때 컴파일러가 컴파일 타임에 불평하지 않으므로 x특정 행이 실행될 때만 런타임 오류가 발생합니다.

따라서 늦은 바인딩의 단점은 여기에 강력한 유형 검사가 없다는 것입니다. 그러나 그것은 또한 장점입니다. 여러 버전이 존재하는 구성 요소가 있고 각 최신 버전이 추가 기능을 제공한다고 가정 해 봅시다. 실제 예제는 Excel COM 인터페이스와 같은 MS Office 구성 요소입니다. 후기 바인딩을 사용하면 모든 버전과 함께 작동하는 코드를 작성할 수 있습니다. 먼저 특정 구성 요소 버전을 확인할 수 있습니다. 사용 가능한 이전 버전 만 해당 버전에서 작동하지 않는 함수 호출을 실행하지 마십시오.


-2

후기 바인딩의 가장 일반적인 예는 인터넷 URL을 확인하는 것입니다. 모든 사이트에 연결하기 전에 세계의 모든 사이트를 연결 및 바인딩하지 않고 동적 시스템 및 대규모 시스템을 지원하지만, 런타임에 약간의 오버 헤드 (DNS 조회, 훨씬 적은 IP 라우팅)가 발생합니다.

이러한 관점에서 언어 환경에서의 대부분의 바인딩은 컴파일 타임이나 링크 타임에 어느 정도 빠릅니다.

각 종류마다 비용과 혜택이 있습니다.


이 바인딩 정의에 대한 참조를 사이트에 제공 할 수 있습니까? 바인딩이 이름을 확인하는 행위이기 때문에 인터넷 주소를 "바인딩"으로 해석하는 것에 대해 들어 본 적이 없습니다. 누군가가 조기 / 늦게 바인딩의 개념을 인터넷 주소에 대한 URI를 해석하는 데 적용 할 수 있다고 주장합니다. 그러나 이것은 일반적인 해석이 아니며 초기 / 늦게 바인딩의 개념은 컴퓨터가 인터넷에 일반적으로 연결된 시간보다 우선합니다.
Jay Elston
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.