In the Alan Kays Definition Of Object Oriented there is this definition that partially I don't understand:

OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme LateBinding of all things.

But what does "LateBinding" means? How can I apply this on a language like C#? And why is this so important?

up vote 12 down vote accepted

“Binding” refers to the act of resolving a method name to a piece of invocable code. Usually, the function call can be resolved at compile time or at link time. An example of a language using static binding is C:

int foo(int x);

int main(int, char**) {
  printf("%d\n", foo(40));
  return 0;
}

int foo(int x) { return x + 2; }

Here, the call foo(40) can be resolved by the compiler. This early allows certain optimizations such as inlining. The most important advantages are:

  • we can do type checking
  • we can do optimizations

On the other hand, some languages defer function resolution to the last possible moment. An example is Python, where we can redefine symbols on the fly:

def foo():
    """"call the bar() function. We have no idea what bar is."""
    return bar()

def bar():
    return 42

print(foo()) # bar() is 42, so this prints "42"

# use reflection to overwrite the "bar" variable
locals()["bar"] = lambda: "Hello World"

print(foo()) # bar() was redefined to "Hello World", so it prints that

bar = 42
print(foo()) # throws TypeError: 'int' object is not callable

This is an example of late binding. While it makes rigorous type checking unreasonably (type checking can only be done at runtime), it is far more flexible and allows us to express concepts that cannot be expressed within the confines of static typing or early binding. For example, we can add new functions at runtime.

Method dispatch as commonly implemented in “static” OOP languages is somewhere in between these two extremes: A class declares the type of all supported operations up front, so these are statically known and can be typechecked. We can then build a simple lookup table (VTable) that points to the actual implementation. Each object contains a pointer to a vtable. The type system guarantees that any object we get will have a suitable vtable, but we have no idea at compile time what the value of this lookup table is. Therefore, objects can be used to pass functions around as data (half the reason why OOP and function programming are equivalent). Vtables can be easily implemented in any language that supports function pointers, such as C.

#define METHOD_CALL(object_ptr, name, ...) \
  (object_ptr)->vtable->name((object_ptr), __VA_ARGS__)

typedef struct {
    void (*sayHello)(const MyObject* this, const char* yourname);
} MyObject_VTable;

typedef struct {
    const MyObject_VTable* vtable;
    const char* name;
} MyObject;

static void MyObject_sayHello_normal(const MyObject* this, const char* yourname) {
  printf("Hello %s, I'm %s!\n", yourname, this->name);
}

static void MyObject_sayHello_alien(const MyObject* this, const char* yourname) {
  printf("Greetings, %s, we are the %s!\n", yourname, this->name);
}

static MyObject_VTable MyObject_VTable_normal = {
  .sayHello = MyObject_sayHello_normal,
};
static MyObject_VTable MyObject_VTable_alien = {
  .sayHello = MyObject_sayHello_alien,
};

static void sayHelloToMeredith(const MyObject* greeter) {
   // we have no idea what the VTable contents of my object are.
   // However, we do know it has a sayHello method.
   // This is dynamic dispatch right here!
   METHOD_CALL(greeter, sayHello, "Meredith");
}

int main() {
  // two objects with different vtables
  MyObject frank = { .vtable = &MyObject_VTable_normal, .name = "Frank" };
  MyObject zorg  = { .vtable = &MyObject_VTable_alien, .name = "Zorg" };

  sayHelloToMeredith(&frank); // prints "Hello Meredith, I'm Frank!"
  sayHelloToMeredith(&zorg); // prints "Greetings, Meredith, we are the Zorg!"
}

This kind of method lookup is also known as “dynamic dispatch”, and somewhere in between of early binding and late binding. I consider dynamic method dispatch to be the central defining property of OOP programming, with anything else (e.g. encapsulation, subtyping, …) to be secondary. It enables us to introduce polymorphism into our code, and even to add new behaviour to a piece of code without having to recompile it! In the C example, anyone can add a new vtable and pass an object with that vtable to sayHelloToMeredith().

While this is late-ish binding, this is not the “extreme late binding” favoured by Kay. Instead of the conceptual model “method dispatch via function pointers”, he uses “method dispatch via message passing”. This is an important distinction because message passing is far more general. In this model, each object has an inbox where other objects can put messages. The receiving object can then try to interpret that message. The most well-known OOP system is the WWW. Here, messages are HTTP requests, and servers are objects.

For example, I can ask the programmers.stackexchange.se server GET /questions/301919/. Compare this to the notation programmers.get("/questions/301919/"). The server can refuse this request or send me back an error, or it can serve me your question.

The power of message passing is that it scales very well: no data is shared (only transferred), everything can happen asynchronously, and objects can interpret messages however they like. This makes a message passing OOP system easily extendable. I can send messages that not everyone may understand, and either get back my expected result or an error. The object need not declare up front which messages it will respond to.

This puts the responsibility of maintaining correctness onto the receiver of a message, a thought also known as encapsulation. E.g. I can't read a file from an HTTP server without asking for it via a HTTP message. This allows the HTTP server to refuse my request, e.g. if I lack permissions. In smaller scale OOP, this means that I don't have read-write access to an object's internal state, but must go through public methods. A HTTP server doesn't have to serve me a file, either. It could be dynamically generated content from a DB. In real OOP, the mechanism of how an object responds to messages can be switched out, without a user noticing. This is stronger than “reflection”, but usually a full meta-object protocol. My C example above cannot change the dispatch mechanism at runtime.

The ability to change the dispatch mechanism implies late binding, since all messages are routed through user-defineable code. And this is extremely powerful: given a meta-object protocol, I can add features such as classes, prototypes, inheritance, abstract classes, interfaces, traits, multiple inheritance, multi-dispatch, aspect-oriented programming, reflection, remote method invocation, proxy objects etc. to a language that does not start out with these features. This power to evolve is completely absent from more static languages such as C#, Java, or C++.

Late binding refers to how objects communicate with each other. The ideal that Alan is trying to achieve is for objects to be as loosely coupled as possible. In other words that an object needs to know the minimum possible in order to communicate with another object.

Why? Because that encourages the ability to change parts of the system independently and affords it to grow and change organically.

For example, in C# you might write in a method for obj1 something like obj2.doSomething(). You can look on this as obj1 communicating with obj2. For this to happen in C#, obj1 needs to know a fair bit about obj2. It will have needed to know its class. It would have checked that the class has a method called doSomething and that there is a version of that method that takes zero parameters.

Now imagine a system where you're sending a message across a network or similar. you might write something like Runtime.sendMsg(ipAddress, "doSomething"). In this case you don't need to know a lot about the machine you're communicating with; it presumably can be contacted via IP and will do something when it receives the "doSomething" string. But otherwise you know very little.

Now imagine that's how objects communicate. You know an address and that you can send arbitrary messages to that address with some kind of "postbox" function. In this case, obj1 doesn't need to know very much about obj2, just it's address. It doesn't even need to know that it understands doSomething.

That's pretty much the crux of late binding. Now, in languages that use it, such as Smalltalk and ObjectiveC, there's usually a bit of syntactic sugar to hide the postbox function. But otherwise the idea is the same.

In C# you could replicate it, sort of, by having a Runtimeclass that accepts an object ref and a string and uses reflection to find the method and invoke it (it'll start getting complicated with arguments and return values but it would be possible though ugly).

Edit: to allay some confusion with regard to the meaning of late binding. In this answer I am referring to late binding as I understand Alan Kay meant it and implemented it in Smalltalk. It is not the more common, modern use of the term which generally refers to dynamic dispatch. The latter covers the delay in resolving the exact method until runtime but still requires some type information for the receiver at compile time.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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