OOP Dispatch: Vinculación Dinámica, Single y Double Dispatch
Este artículo es una aclaración de conceptos sobre dispatch en programación orientada a objetos, incluyendo preguntas de examen y etiquetas.
En Resumen
Dispatch es la selección del método que realmente se ejecuta cuando se realiza una llamada. Según el lenguaje y la construcción utilizada, la vinculación ocurre de forma estática en tiempo de compilación o dinámicamente en tiempo de ejecución, siendo la base de la polimorfía.
Descripción Técnica Compacta
El dispatch es la resolución de una llamada a método hacia una implementación concreta. Con dispatch estático (sobrecarga), el compilador decide basándose en los tipos estáticos. Con dispatch dinámico (sobrescritura), el entorno de ejecución decide basándose en el tipo real del objeto, frecuentemente a través de una vtable.
Variantes de dispatch:
- Single Dispatch: La selección se basa en el objeto receptor
- Double Dispatch: La selección se basa en dos tipos en tiempo de ejecución (Visitor Pattern)
- Multiple Dispatch: La selección se basa en múltiples argumentos en tiempo de ejecución
La vinculación dinámica permite polimorfía y el Open Closed Principle, pero requiere contratos correctos según el Liskov Substitution Principle. El dispatch estático ofrece previsibilidad y rendimiento, mientras que el dispatch dinámico proporciona flexibilidad y extensibilidad.
Puntos Clave para Examen
- Dispatch estático: Sobrecarga, decisión en tiempo de compilación
- Dispatch dinámico: Sobrescritura, decisión en tiempo de ejecución
- vtable: Tabla de dispatch para llamadas polimórficas
- Single Dispatch: Solo el tipo del receptor decide
- Double Dispatch: El receptor y el parámetro deciden
- Visitor Pattern: Implementa double dispatch
- Rendimiento: El dispatch estático es más rápido que el dinámico
- Relevancia de examen: Distinción entre sobrecarga y sobrescritura
Componentes Principales
- Virtual Method Table (vtable): Tabla de dispatch para métodos polimórficos
- Single Dispatch: Mecanismo de dispatch estándar en OOP
- Double Dispatch: Visitor Pattern para relaciones de tipos complejas
- Method Overriding: Vinculación dinámica en herencia
- Method Overloading: Vinculación estática en tiempo de compilación
- Runtime Type Information (RTTI): Información de tipos en tiempo de ejecución
- Dynamic Binding: Resolución en tiempo de ejecución
- Static Binding: Resolución en tiempo de compilación
Ejemplos Prácticos
Single Dispatch (OOP Estándar)
// Single Dispatch - solo el tipo del receptor decide
abstract class Tier {
abstract void machGeraeusch();
}
class Hund extends Tier {
@Override
void machGeraeusch() {
System.out.println("Wuff!");
}
}
class Katze extends Tier {
@Override
void machGeraeusch() {
System.out.println("Miau!");
}
}
// Vinculación dinámica en tiempo de ejecución
Tier tier = new Hund(); // Tipo estático: Tier, Tipo dinámico: Hund
tier.machGeraeusch(); // Output: "Wuff!" (Single Dispatch)
Double Dispatch con Visitor Pattern
// Double Dispatch - receptor y parámetro deciden
interface Tier {
void akzeptiere(Besucher besucher);
}
class Hund implements Tier {
@Override
public void akzeptiere(Besucher besucher) {
besucher.besuche(this); // Double Dispatch
}
}
class Katze implements Tier {
@Override
public void akzeptiere(Besucher besucher) {
besucher.besuche(this); // Double Dispatch
}
}
interface Besucher {
void besuche(Hund hund);
void besuche(Katze katze);
}
class Tierarzt implements Besucher {
@Override
public void besuche(Hund hund) {
System.out.println("Untersuche Hund: Impfung geben");
}
@Override
public void besuche(Katze katze) {
System.out.println("Untersuche Katze: Krallen schneiden");
}
}
// Uso
Tier[] tiere = {new Hund(), new Katze()};
Besucher tierarzt = new Tierarzt();
for (Tier tier : tiere) {
tier.akzeptiere(tierarzt); // Double Dispatch
}
// Output:
// Untersuche Hund: Impfung geben
// Untersuche Katze: Krallen schneiden
Dispatch Estático vs Dinámico
class Rechner {
// Dispatch estático (Overloading)
public int addiere(int a, int b) {
return a + b;
}
public double addiere(double a, double b) {
return a + b;
}
}
class PolymorpherRechner {
// Dispatch dinámico (Overriding)
public virtual int berechne(int a, int b) {
return a + b;
}
}
class Multiplizierer extends PolymorpherRechner {
@Override
public int berechne(int a, int b) {
return a * b;
}
}
// Dispatch estático en tiempo de compilación
Rechner rechner = new Rechner();
int ergebnis1 = rechner.addiere(1, 2); // Compile: addiere(int, int)
// Dispatch dinámico en tiempo de ejecución
PolymorpherRechner poly = new Multiplizierer();
int ergebnis2 = poly.berechne(3, 4); // Runtime: Multiplizierer.berechne()
Ventajas y Desventajas
Ventajas del Dispatch Dinámico
- Flexibilidad: La polimorfía en tiempo de ejecución permite sistemas extensibles
- Mantenibilidad: Agregar nuevos tipos sin cambiar código existente
- Abstracción: Tratamiento uniforme de diferentes tipos
- Open Closed Principle: Extensible sin modificación
Desventajas
- Rendimiento: Overhead en tiempo de ejecución por búsqueda en vtable
- Complejidad: Más difícil de entender y depurar
- Memoria: Estructuras adicionales de vtable
- Propensión a errores: Errores en tiempo de ejecución en lugar de tiempo de compilación
Mecanismos de Dispatch en Diferentes Lenguajes
Java
// Estándar: Single Dispatch con vtable
// Double Dispatch a través del Visitor Pattern
interface Shape {
double area();
void accept(Visitor visitor);
}
C++
// Soporte directo: Multiple Dispatch
#include <boost/variant.hpp>
struct DoubleDispatcher {
void collide(Asteroid& a, Spaceship& s) { /* ... */ }
void collide(Spaceship& s, Asteroid& a) { /* ... */ }
};
Python
# Duck Typing: Resolución dinámica
class Animal:
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
return "Woof!"
# Vinculación dinámica en tiempo de ejecución
def animal_sound(animal):
return animal.make_sound() # Dispatch en tiempo de ejecución
Preguntas Frecuentes de Examen
-
¿Cuál es la diferencia entre Single y Double Dispatch? Single Dispatch solo considera el tipo del receptor, mientras que Double Dispatch considera tanto el tipo del receptor como los tipos de los parámetros.
-
¿Cómo funciona una vtable? Una vtable es un array de punteros a funciones que resuelve llamadas a métodos polimórficos en tiempo de ejecución.
-
¿Cuándo se utiliza el Visitor Pattern? Cuando las operaciones deben separarse de la estructura de datos y se requiere double dispatch.
-
¿Por qué el dispatch dinámico es más lento que el estático? Porque requiere una búsqueda en vtable en tiempo de ejecución en lugar de llamadas directas a métodos en tiempo de compilación.
Fuentes Importantes
- https://de.wikipedia.org/wiki/Dynamische_Bindung
- https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
- https://refactoring.guru/de/design-patterns/visitor
Continúa en la Ruta de Aprendizaje de OOP
Todos los artículos de OOP están ahora completos. Vuelve al primer artículo: Objektorientierte Programmierung OOP Grundlagen.



