« Back to Design Patterns in Object-Oriented Programming

CONCEPTS


Contents:


Binding

Binding in programming refers to relating (i.e. “binding” or “resolving”) identifiers to either their implementations (i.e. stored instructions) or memory locations (i.e. stored data or allocated space for storing data). Note that (1) these identifiers may be identify either data (e.g. variables), data references (e.g. pointers) or functions, and (2) for the machine, “relating” identifiers to their implementations or memory locations means replacing source text with machine-executable instructions or data.

SIDE NOTE: Objects are a kind of data structure, and object methods are a kind of function. Hence, whatever has been given for binding in programming also applies to object-oriented programming.

Static binding

Example:

void my_function(int x, int y) { ... }  // Resolved at compile-time

Dynamic binding

Also called “late” binding, as it is done during runtime.

Example:

def process(obj):
    obj.method()  # Resolved at runtime based on obj's type

* Duck typing is an approach to resolving an object’s type based not on its declared type but on its interface and valid behaviour (i.e. valid object methods). For reference, the name “duck typing” is a reference to the “duck test”, a widely cited example of abductive reasoning.

Reference: Duck Typing in Python: Writing Flexible and Decoupled Code from RealPython.com

Key time periods relevant to binding

  1. Compile-time: Type checking, overload resolution
  2. Link-time: Symbol resolution across compilation units
  3. Load-time: Dynamic library resolution
  4. Runtime: Virtual method dispatch, dynamic typing

Performance implications

Static binding enables compiler optimisations but reduces flexibility. Dynamic binding offers greater flexibility at performance cost.

The importance of dynamic binding in OOP

The run-time association of a request to an object and one of its operations is known as dynamic binding. Dynamic binding means that issuing a request does not commit you to a particular implementation until run-time. Consequently, you can write programs that expect an object with a particular interface, knowing that any object that has the correct interface will accept the request. Moreover, dynamic binding lets you substitute objects that have identical interfaces for each other at run-time. This substitutability is known as polymorphism, and it is a key concept in object-oriented systems.

Reference: DPG4 (p. 45)

Class

A class is the definition of an object, i.e. it is a set of stored instructions that specifies (1) the object’s identity (i.e. its attributes and methods), and (2) how an object must be created during runtime. Note that an object is called an “instance” of its class, analogous to a concept and its referents; just as one concept (encapsulated by a definition) can have multiple referents, one class can have multiple instances. Hence:

NOTE: Not all classes are meant to be instantiated; e.g. abstract classes.

For further clarity, see how class is related to interface.

Encapsulation

Encapsulation refers to restricting direct access to an object’s attributes and methods. Hence, it “encapsulates”, i.e. packages data and procedures, and protects access to them via objects. Hence, it is the key aspect of an object.


For more clarity, here are some key points about objects:

Due to these restrictions, an object’s attributes and methods are encapsulated, i.e. (1) its attributes and methods cannot be accessed directly, i.e. without referring them through the object, and (2) the implementation of an object’s state and behaviour is invisible from outside the object.

Reference: DPG4 (p. 42)

Framework

A framework is a set of cooperating classes that make up a reusable design for a specific class of software. Note that you customise a framework by creating application-specific subclasses of abstract classes from the framework. As examples of frameworks, a framework can be made for building:

Hence, frameworks:

Design patterns vs. frameworks:

Reference: DPG4 (p. 65-68)

Inheritance and polymorphism

Objects with identical interfaces may have different implementations of the methods that fulfill these requests, often made possible by inheritance and polymorphism. Inheritance allows subclasses to implement or override methods from a parent class, while polymorphism ensures that objects of different implementations can be treated uniformly when they share the same interface.

Inheritance

Inheritance is the concept of containing one object’s implementation and/or interface as a part of another object’s implementation and/or interface. In effect, the latter object “inherits” the attributes and methods of the former object, allowing the latter to reuse and extend the functionality of the former.

Class vs. interface inheritance

An object’s class defines how the object is implemented. The class defines the object’s internal state and the implementation of its operations. In contrast, an object’s type only refers to its interface, i.e. the set of requests to which it can respond. An object can have many types, and objects of different classes can have the same type.

Reference: DPG4 (p. 49)

Polymorphism

Polymorphism is the concept of enabling different objects or functions to behave differently while sharing the same type (for objects) or name (for functions). In other words, it enables (1) a single function/method identifier to handle different requests, i.e. different parameters (here, the identifier and the request together identify the function), or (2) different objects to respond differently to the same request made from a shared interface.


Polymorphism simplifies the definitions of clients, decouples objects from each other, and lets them vary their relationships to each other at run-time. (direct quote from the book)


Check here for more clarity of polymorphism.

Reference: DPG4 (p. 44-45)

Interface

A method’s name, parameters, and return value are together called the method’s signature. The set of the signatures of the methods declared by an object is called the object’s interface. An object’s interface characterizes the complete set of requests that can be sent to the object. Any request that matches a signature in the object’s interface may be sent to the object.

NOTE: Interfaces can contain other interfaces as subsets.

Interfaces are fundamental in object-oriented systems, since objects are known only through their interfaces. There is no way to know anything about an object or make any requests to it without dealing with its interface. An object’s interface is not tied to its implementation, i.e., its class. Two objects having different implementations (e.g., derived from different classes or subclasses) can have identical interfaces. For example, both Dog and Cat classes can implement an Animal interface with the method signature make_sound(), but have different implementations:

class Animal:
    def make_sound(self):
        pass  # method signature in the interface

class Dog(Animal):
    def make_sound(self):
        print("Bark!")

class Cat(Animal):
    def make_sound(self):
        print("Meow!")

Further reading for clarity

Reference: DPG4 (p. 44-45)

Method

Also called “operation”*.

A method is a functions whose access is managed by an object. Hence, a method is always of an object. Encapsulation further clarifies the role of a method.


* This term is less common and has other meanings outside OOP.

Object

Design-level definition

An object is a well-defined representation* of a functional unit (i.e. a unit that can act and interact as a well-defined whole, e.g. an entity, a phenomenon, a functionality, etc.). To this end, an object represents both the state and the behaviour of the functional unit.

* A representation of X is a mapping between X and some other entity or system Y, done such that, within a specific context, changes to Y exactly map to changes to X and vice versa.


In essence, an object models a functional unit with both:

For encapsulating usage, an object presents an interface that:

For abstracting implementation details, it manages:


Hence, an object is not just a way to organise code, but a design tool for breaking down complex systems into manageable components that map to real concepts in the problem domain.

Implementation-level definition

Given how it is implemented with our existing technology.

An object is a data structure that stores and gives access to (1) data or references to data and (2) the procedures designed to operate on these data. These data and references to data are called “attributes”, and procedures are called “methods”. The values of its attributes are together the object’s state, and the execution of the object’s methods (i.e. the object’s “actions”) is the object’s behaviour. An object is implemented through a class.

NOTE. The purpose of an object is to organise and manage access to data and procedures with respect to a unifying idea or purpose (e.g. an entity, a phenomenon, a functionality, etc.); typically, this is an idea or purpose that ties into the broader purpose of a module or application.

Linking design-level and implementation-level

The technical implementation of an object (at least the way it has been done so far) uses data structures, but in a conceptual design/architecture context, an object is about encapsulation and abstraction rather than data organisation. As analogy, describing a car as “a collection of metal parts” gives the truth but does not give the essence of what a car is and does. That said, to be precise about its implementation, an object is realised as a data structure that contains:

For greater clarity, see:

Toolkit

A toolkit is a library, i.e. a set of related and reusable classes designed to provide useful, general-purpose functionality. They let you as an implementer avoid recoding common functionality. Examples of toolkits: a set of collection classes for (1) lists, associative tables, stacks, (2) visualisation (e.g. Matplotlib in Python).

NOTE: Toolkits do not impose a particular design on your application and just provide functionality that can help your application do its job; toolkits are design-agnostic Toolkits emphasise code reuse.

Reference: DPG4 (p. 65)

Type

A type is a name used to denote a particular interface. E.g. an object has the type “Rectangle” if it accepts all requests for the methods defined in the interface named “Rectangle”. This name may just be the name of the object’s class or some ancestor class of its class, but not necessarily, since one object may have more than one type (i.e. it can be interacted with via more than one interface), and different objects with very different identities (possibly even unrelated class hierarchies) can share a type. A type is a subtype of another type (its supertype) if the interface it refers to contains the interface of its supertype. Often, a subtype is said to “inherit” the interface of its supertype.



Additional conceptual topics

Relating class and interface

There is a close relationship between class and interface. Because a class defines the operations an object can perform, it also defines the object’s type. When we say that an object is an instance of a class, we imply that the object supports the interface defined by the class.

Reference: DPG4 (p. 49)