En la definición de Alan Kays de orientado a objetos existe esta definición que parcialmente no entiendo:
OOP para mí significa solo mensajes, retención local y protección y ocultación de procesos estatales, y LateBinding extremo de todas las cosas.
Pero, ¿qué significa "LateBinding"? ¿Cómo puedo aplicar esto en un lenguaje como C #? ¿Y por qué es esto tan importante?
object-oriented
object-oriented-design
Luca Zulian
fuente
fuente
Respuestas:
"Enlace" se refiere al acto de resolver el nombre de un método a un fragmento de código invocable. Por lo general, la llamada a la función se puede resolver en tiempo de compilación o en tiempo de enlace. Un ejemplo de un lenguaje que usa enlace estático es C:
Aquí, la llamada
foo(40)
puede ser resuelta por el compilador. Esto temprano permite ciertas optimizaciones como la alineación. Las ventajas más importantes son:Por otro lado, algunos idiomas difieren la resolución de la función hasta el último momento posible. Un ejemplo es Python, donde podemos redefinir símbolos sobre la marcha:
Este es un ejemplo de encuadernación tardía. Si bien hace que la verificación de tipos rigurosa sea irrazonable (la verificación de tipos solo se puede hacer en tiempo de ejecución), es mucho más flexible y nos permite expresar conceptos que no se pueden expresar dentro de los límites de la escritura estática o la vinculación temprana. Por ejemplo, podemos agregar nuevas funciones en tiempo de ejecución.
El envío de métodos implementado comúnmente en lenguajes OOP "estáticos" se encuentra en algún punto entre estos dos extremos: una clase declara el tipo de todas las operaciones admitidas por adelantado, por lo que estas son estáticamente conocidas y se pueden verificar. Luego podemos construir una tabla de búsqueda simple (VTable) que apunte a la implementación real. Cada objeto contiene un puntero a una vtable. El sistema de tipos garantiza que cualquier objeto que obtengamos tenga una vtable adecuada, pero en el momento de la compilación no tenemos idea de cuál es el valor de esta tabla de búsqueda. Por lo tanto, los objetos se pueden usar para pasar funciones como datos (la mitad de la razón por la cual la programación de funciones y OOP son equivalentes). Vtables se puede implementar fácilmente en cualquier lenguaje que admita punteros de función, como C.
Este tipo de búsqueda de método también se conoce como "despacho dinámico", y en algún punto intermedio entre el enlace temprano y el enlace tardío. Considero que el despacho de métodos dinámicos es la propiedad de definición central de la programación OOP, con cualquier otra cosa (por ejemplo, encapsulación, subtipo, ...) como secundaria. ¡Nos permite introducir polimorfismo en nuestro código e incluso agregar un nuevo comportamiento a un fragmento de código sin tener que volver a compilarlo! En el ejemplo de C, cualquiera puede agregar una nueva vtable y pasarle un objeto con esa vtable
sayHelloToMeredith()
.Si bien este es un enlace tardío, este no es el "enlace tardío extremo" favorecido por Kay. En lugar del modelo conceptual "envío de métodos a través de punteros de función", utiliza "envío de métodos a través del paso de mensajes". Esta es una distinción importante porque el paso de mensajes es mucho más general. En este modelo, cada objeto tiene una bandeja de entrada donde otros objetos pueden poner mensajes. El objeto receptor puede intentar interpretar ese mensaje. El sistema OOP más conocido es el WWW. Aquí, los mensajes son solicitudes HTTP y los servidores son objetos.
Por ejemplo, puedo preguntarle al servidor programmers.stackexchange.se
GET /questions/301919/
. Compare esto con la notaciónprogrammers.get("/questions/301919/")
. El servidor puede rechazar esta solicitud o devolverme un error, o puede responderme su pregunta.El poder de pasar mensajes es que se escala muy bien: no se comparten datos (solo se transfieren), todo puede suceder de forma asincrónica y los objetos pueden interpretar los mensajes como quieran. Esto hace que un mensaje que pasa el sistema OOP sea fácilmente extensible. Puedo enviar mensajes que no todos pueden entender y recuperar mi resultado esperado o un error. El objeto no necesita declarar por adelantado a qué mensajes responderá.
Esto pone la responsabilidad de mantener la corrección en el receptor de un mensaje, un pensamiento también conocido como encapsulación. Por ejemplo, no puedo leer un archivo de un servidor HTTP sin pedirlo a través de un mensaje HTTP. Esto permite que el servidor HTTP rechace mi solicitud, por ejemplo, si no tengo permisos. En OOP de menor escala, esto significa que no tengo acceso de lectura y escritura al estado interno de un objeto, sino que debo pasar por métodos públicos. Un servidor HTTP tampoco tiene que servirme un archivo. Podría ser contenido generado dinámicamente desde una base de datos. En OOP real, el mecanismo de cómo un objeto responde a los mensajes se puede cambiar sin que el usuario lo note. Esto es más fuerte que la "reflexión", pero generalmente es un protocolo completo de metaobjetos. Mi ejemplo C anterior no puede cambiar el mecanismo de envío en tiempo de ejecución.
La capacidad de cambiar el mecanismo de envío implica un enlace tardío, ya que todos los mensajes se enrutan a través de un código definible por el usuario. Y esto es extremadamente poderoso: dado un protocolo de metaobjetos, puedo agregar características como clases, prototipos, herencia, clases abstractas, interfaces, rasgos, herencia múltiple, despacho múltiple, programación orientada a aspectos, reflexión, invocación de método remoto, objetos proxy, etc. a un lenguaje que no comienza con estas características. Este poder para evolucionar está completamente ausente de lenguajes más estáticos como C #, Java o C ++.
fuente
El enlace tardío se refiere a cómo los objetos se comunican entre sí. El ideal que Alan está tratando de lograr es que los objetos estén tan flojos como sea posible. En otras palabras, un objeto necesita saber el mínimo posible para comunicarse con otro objeto.
¿Por qué? Porque eso fomenta la capacidad de cambiar partes del sistema de forma independiente y le permite crecer y cambiar orgánicamente.
Por ejemplo, en C # puede escribir un método para
obj1
algo asíobj2.doSomething()
. Puedes ver esto comoobj1
comunicarte conobj2
. Para que esto suceda en C #,obj1
necesita saber un poco sobreobj2
. Habría necesitado saber su clase. Habría comprobado que la clase tiene un método llamadodoSomething
y que hay una versión de ese método que toma cero parámetros.Ahora imagine un sistema donde envía un mensaje a través de una red o similar. se podría escribir algo así como
Runtime.sendMsg(ipAddress, "doSomething")
. En este caso, no necesita saber mucho sobre la máquina con la que se está comunicando; presumiblemente se puede contactar a través de IP y hará algo cuando reciba la cadena "doSomething". Pero por lo demás sabes muy poco.Ahora imagine que así es como se comunican los objetos. Usted conoce una dirección y puede enviar mensajes arbitrarios a esa dirección con algún tipo de función de "buzón de correo". En este caso,
obj1
no necesita saber muchoobj2
, solo su dirección. Ni siquiera necesita saber que entiendedoSomething
.Eso es más o menos el quid de la unión tardía. Ahora, en los lenguajes que lo usan, como Smalltalk y ObjectiveC, generalmente hay un poco de azúcar sintáctica para ocultar la función de buzón. Pero por lo demás, la idea es la misma.
En C #, podría replicarlo, más o menos, al tener una
Runtime
clase que acepte una referencia de objeto y una cadena y use la reflexión para encontrar el método e invocarlo (comenzará a complicarse con argumentos y valores de retorno, pero sería posible aunque feo).Editar: para disipar cierta confusión con respecto al significado del enlace tardío. En esta respuesta me refiero al enlace tardío porque entiendo que Alan Kay lo quiso decir y lo implementó en Smalltalk. No es el uso más común y moderno del término lo que generalmente se refiere al despacho dinámico. Este último cubre el retraso en la resolución del método exacto hasta el tiempo de ejecución, pero aún requiere cierta información de tipo para el receptor en tiempo de compilación.
fuente