86

I keep hearing about early and late binding, but I do not understand what they are. I found the following explanation which I do not understand:

Early binding refers to assignment of values to variables during design time whereas late binding refers to assignment of values to variables during run time.

Could someone please define the two types of binding and compare them?

2

7 Answers 7

93

There are two major concepts in confusion: binding and loading. It is conflated by the concept of DataBinding, which is somewhere in the middle often doing both. After considering it, I am going to add one more concept, to complete the trifecta, dispatch.

Types

Late Binding: type is unknown until the variable is exercised during run-time; usually through assignment but there are other means to coerce a type; dynamically typed languages call this an underlying feature, but many statically typed languages have some method of achieving late binding

Implemented often using [special] dynamic types, introspection/reflection, flags and compiler options, or through virtual methods by borrowing and extending dynamic dispatch

Early Binding: type is known before the variable is exercised during run-time, usually through a static, declarative means

Implemented often using standard primitive types

Functions

Static Dispatch: known, specific function or subroutine at compile time; it is unambiguous and matched by the signature

Implemented as static functions; no method can have the same signature

Dynamic Dispatch: not a specific function or subroutine at compile time; determined by the context during execution. There are two different approaches to "dynamic dispatch," distinguished by what contextual information is used to select the appropriate function implementation.

In single [dynamic] dispatch, only the type of the instance is used to determine the appropriate function implementation. In statically-typed languages, what this means in practice is that the instance type decides which method implementation is used irrespective of the reference type indicated when the variable is declared/assigned. Because only a single type -- the type of the object instance -- is used to infer the appropriate implementation, this approach is called "single dispatch".

There is also multiple [dynamic] dispatch, where input parameter types also help determine which function implementation to call. Because multiple types -- both the type of the instance and the type(s) of the parameter(s) -- influence which method implementation is selected, this approach is dubbed "multiple dispatch".

Implemented as virtual or abstract functions; other clues include overridden, hidden, or shadowed methods.

NB: Whether or not method overloading involves dynamic dispatch is language-specific. For example, in Java, overloaded methods are statically dispatched.

Values

Lazy Loading: object initialization strategy that defers value assignment until needed; allows an object to be in an essentially valid but knowingly incomplete state and waiting until the data is needed before loading it; often found particularly useful for loading large datasets or waiting on external resources

Implemented often by purposefully not loading a collection or list into a composite object during the constructor or initialization calls until some downstream caller asks to see the contents of that collection (eg. get_value_at, get_all_as, etc). Variations include loading meta information about the collection (like size or keys), but omitting the actual data; also provides a mechanism to some runtimes to provide developers with a fairly safe and efficient singleton implementation scheme

Eager Loading: object initialization strategy that immediately performs all value assignments in order to have all the data needed to be complete before considering itself to be in a valid state.

Implemented often by providing a composite objects with all their known data as soon as possible, like during a constructor call or initialization

Data Binding: often involves creating an active link or map between two compatible information streams so that changes to one are reflected back into the other and vice versa; in order to be compatible they often have to have a common base type, or interface

Implemented often as an attempt to provide cleaner, consistent synchronization between different application aspects (eg view-model to view, model to controller, etc.) and talks about concepts like source and target, endpoints, bind/unbind, update, and events like on_bind, on_property_change, on_explicit, on_out_of_scope


EDIT NOTE: Last major edit to provide description of examples of how these often occur. Particular code examples depend entirely on the implementation/runtime/platform

3
  • 2
    This answer seems too specific to object-oriented languages.
    – Jack
    Dec 5, 2015 at 19:31
  • @Jack I don't feel this way, I think this is an excellent that covers many aspects.
    – laike9m
    Dec 26, 2019 at 1:05
  • Any concrete example of statically typed language with late binding?
    – wlnirvana
    Apr 29, 2022 at 4:22
27

Anything that is decided by compiler while compiling can be refer to EARLY/COMPILE TIME Binding and anything that is to be decided at RUNTIME is called LATE/RUNTIME binding.

For Example,

Method Overloading and Method Overriding.

1) In Method Overloading your method calls to the methods are decided by the compiler in the sense that which function is going to be called is decided by your compiler at compile time. Hence being EARLY BINDING.

2) In method Overriding, it is decided at RUNTIME which method is going to be called. So it is reffered as LATE BINDING.

Tried to keep it simple and easy to get. Hope this helps.

9

Late binding is when behavior is evaluated at runtime. It's necessary when you indeed want to determine how to act based on information you only have when the program is running. The clearest example in my opinion is the virtual function mechanism, specifically in 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();
}

In this example,a->f() will actually call void A::f(), because it's early (or statically) bound, and so the program at runtime thinks it's just a pointer to an A type variable, whereas a->g() will actually call void B::g(), because the compiler, seeing g() is virtual, injects code to look up the address of the correct function to call at runtime.

6
  • 1
    "The runtime"? You're talking about C++. C++ compiles straight to machine code, it doesn't need a runtime to resolve virtual methods.
    – tdammers
    Jun 1, 2013 at 6:16
  • 3
    @tdammers C++ actually does need a run time library, though not for virtual calls. If you read carefully, you'll notice that this answer says the compiler "injects code to look up the address of the correct function [...] at runtime".
    – user7043
    Jun 1, 2013 at 8:50
  • Well, but that "code to look up the address of the correct function" is basically just a type-agnostic two-stage pointer dereference followed by a function call. There is no "thinking" involved; the only reason it works reliably is because the compiler does the type checking at compile time; at run-time, the generated code trusts the compiler to have done the type-checking homework. If you use unsafe casts (e.g. C-style pointer casts), you can legally treat C++ objects as object of the wrong class, but their vtables will be utterly messed up and the code just breaks.
    – tdammers
    Jun 1, 2013 at 11:56
  • @tdammers I tried to stay away from that kind of answer, because it's an implementation detail of compilers, which might, or might not be true for some esoteric compiler. What matters is the concept. Jun 1, 2013 at 13:34
  • 1
    @tdammers And by "the runtime" I mean "the program at runtime". Obviously C++ isn't managed. But since you showed me it can cause confusion, I'm changing it to the full wording. Jun 1, 2013 at 13:36
5

if you are familiar with function pointers this would be an example. Functions defined can be said to be Early binding . whereas if you use Function pointers its late Binding.

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

here functions add and sub are functions (its address are binded at compile time-linker)

but the function pointer is late binding the fp can call either add or sub depending on user choice [at runtime].

3

Early and late binding only make sense in the context of types and not the way you are describing it. Pretty much all modern languages are typed in the sense that all values have fixed types. The difference comes in when we look at dynamically vs statically typed languages. In dynamically typed languages variables don't have types so they can refer to values of any type and this means that when you call a method on an object referred to by some variable the only way to determine whether that call is valid or not is to look up the class for the object and see if that method actually exists. This allows for some cool things like adding new methods to classes at run time because the actual method lookup is deferred up until the very last moment. Most people call this state of affairs late binding.

In a statically typed language variables have types and once declared can not refer to any value that is not of the same type. This isn't strictly true but lets assume it for now. Now if you know that the variable will only ever refer to values of a specific type then there is no reason to figure out if a method call is valid or not at run time because you can determine the validity before the code is ever run. This is referred to as early binding.

An example to demonstrate late binding in ruby:

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

The above sequence of actions is not possible in a language like Java where all types are fixed at run time.

1

Instead of giving you an academic definition I will try to show you some of the differences using a real world example using VBA:

Early binding:

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

This requires a reference to be set to the "Microsoft Scripting Runtime" component at design time. It has the advantage that you get an error message already at compile time when you have a typo in FileSystemObject or method names like GetSpecialFolder.

Late binding

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

This does not require a reference to be set beforehand, the instance creation and type determination will just happen at run-time. The compiler won't complain at compile-time when you try to call a non-existent method of x, this will lead to a run-time error only when the specific line is executed.

So, the disadvantage of late binding is that you don't have any strong type checking here. But that is also the advantage - let's say you have a component where several versions exist, and each newer version provides some additional functions. (A real-world example are the MS Office components, like the Excel COM interface) Late binding allows you write code which works together with all of that versions - you can first determine the specific component version, and if you find out that you have only an older version available, avoid to execute functions calls which don't work with that version.

-2

Perhaps the most common example of late binding is resolving Internet URLs. It supports dynamic systems and large systems without trying to link and bind every site in the world before you can reach any, but on the other hand it does incur some overhead (DNS lookup, much less IP routing) at runtime.

By that light, most varieties of binding in language environments is more or less early, at compile time or link time.

Each kind has costs and benefits.

1
  • Can you site a reference for this definition of binding? I have not heard of resolving internet addresses as "binding", although since binding is the act of resolving names, I suppose someone has argued that the concept of early / late binding can be applied to resolving URI to internet addresses. But this is not a common interpretation, and the concept of early / late binding predates the the time where computers were commonly connected to the internet.
    – Jay Elston
    Jan 27, 2016 at 15:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.