stringtranslate.com

Sistema de objetos Common Lisp

Combinación de métodos estándar en ANSI Common Lisp

El Common Lisp Object System (CLOS) es la herramienta para la programación orientada a objetos de ANSI Common Lisp . CLOS es un potente sistema de objetos dinámico que difiere radicalmente de las herramientas de programación orientada a objetos que se encuentran en lenguajes más estáticos como C++ o Java . CLOS se inspiró en sistemas de objetos Lisp anteriores como MIT Flavors y CommonLoops , aunque es más general que ambos. Originalmente propuesto como un complemento, CLOS se adoptó como parte del estándar ANSI para Common Lisp y se ha adaptado a otros dialectos Lisp como EuLisp o Emacs Lisp . [1]

Características

Los componentes básicos de CLOS son los métodos , las clases , las instancias de esas clases y las funciones genéricas . CLOS proporciona macros para definirlas: defclass, defmethod, y defgeneric. Las instancias se crean con el método make-instance.

Las clases pueden tener varias superclases , una lista de ranuras (variables miembro en el lenguaje de C++/Java) y una metaclase especial . Las ranuras se pueden asignar por clase (todas las instancias de una clase comparten la ranura) o por instancia. Cada ranura tiene un nombre y se puede acceder al valor de una ranura por ese nombre utilizando la función slot-value. Además, se pueden definir funciones genéricas especiales para escribir o leer valores de ranuras. Cada ranura en una clase CLOS debe tener un nombre único.

CLOS es un sistema de envío múltiple . Esto significa que los métodos pueden especializarse en cualquiera o todos sus argumentos requeridos. La mayoría de los lenguajes OO son de envío único, lo que significa que los métodos solo se especializan en el primer argumento. Otra característica inusual es que los métodos no "pertenecen" a las clases; las clases no proporcionan un espacio de nombres para funciones o métodos genéricos. Los métodos se definen por separado de las clases y no tienen acceso especial (por ejemplo, "this", "self" o "protected") a los espacios de clase.

Los métodos en CLOS se agrupan en funciones genéricas . Una función genérica es un objeto que se puede llamar como una función y que asocia una colección de métodos con un nombre compartido y una estructura de argumentos, cada uno especializado para diferentes argumentos. Dado que Common Lisp proporciona clases que no son de CLOS para estructuras y tipos de datos integrados (números, cadenas, caracteres, símbolos, ...), CLOS dispatch también funciona con estas clases que no son de CLOS. CLOS también admite el envío sobre objetos individuales (eql specializers). CLOS no admite de forma predeterminada el envío sobre todos los tipos de datos de Common Lisp (por ejemplo, dispatch no funciona para tipos de matriz completamente especializados o para tipos introducidos por deftype). Sin embargo, la mayoría de las implementaciones de Common Lisp proporcionan un protocolo de metaobjetos que permite que las funciones genéricas proporcionen especialización específica de la aplicación y reglas de envío.

El envío en CLOS también es diferente al de la mayoría de los lenguajes OO:

  1. Dada una lista de argumentos, se determina una lista de métodos aplicables.
  2. Esta lista está ordenada según la especificidad de sus parámetros especializados.
  3. Luego, los métodos seleccionados de esta lista se combinan en un método efectivo utilizando la combinación de métodos utilizada por la función genérica.
  4. Luego se llama al método efectivo con los argumentos originales.

Este mecanismo de envío funciona en tiempo de ejecución. Por lo tanto, agregar o eliminar métodos puede provocar que se modifiquen los métodos efectivos (incluso cuando se llama a la función genérica con los mismos argumentos) en tiempo de ejecución. Cambiar la combinación de métodos también puede provocar que los métodos efectivos sean diferentes.

Por ejemplo,

; Declara el prototipo de estructura de argumento común. ( defgeneric f ( x y ))   ; Defina una implementación para (f entero y), donde y coincide con todos los tipos. ( defmethod f (( x entero ) y ) 1 )     ( f1 2.0 ) = > 1    ; Defina una implementación para (f entero real). ( defmethod f (( x entero ) ( y real )) 2 )      ( f 1 2.0 ) => 2 ;El envío se modificó en tiempo de ejecución.     

Al igual que los sistemas OO en la mayoría de los lenguajes dinámicos , CLOS no impone la encapsulación . Se puede acceder a cualquier ranura mediante la función o a través de métodos de accesoslot-value (opcionalmente generados automáticamente) . Para acceder a ella, debe conocer el nombre de la ranura. Los programadores de CL utilizan la función de paquetes del lenguaje para declarar qué funciones o estructuras de datos están destinadas a la exportación.slot-value

Además de los métodos normales ("primarios"), también existen los métodos :before, :after, y :around"auxiliares". Los dos primeros se invocan antes o después del método principal, en un orden particular basado en la jerarquía de clases. Un :aroundmétodo puede controlar si se ejecuta el método principal. Además, el programador puede especificar si se deben invocar todos los métodos principales posibles a lo largo de la jerarquía de clases o solo el que proporcione la coincidencia más cercana.

La combinación de métodos estándar proporciona los métodos primarios, anteriores, posteriores y alternativos explicados anteriormente. Existen otras combinaciones de métodos con otros tipos de métodos. Se pueden definir nuevas combinaciones de métodos (tanto simples como complejas) y tipos de métodos.

CLOS permite la herencia múltiple . Cuando el orden predeterminado en el que se ejecutan los métodos en la herencia múltiple no es correcto, el programador puede resolver los problemas de herencia en rombo especificando el orden de las combinaciones de métodos.

CLOS es dinámico, lo que significa que no sólo el contenido, sino también la estructura de sus objetos pueden modificarse en tiempo de ejecución. CLOS permite cambiar las definiciones de clase sobre la marcha (incluso cuando ya existen instancias de la clase en cuestión), así como cambiar la pertenencia a una clase determinada mediante el change-classoperador. CLOS también permite añadir, redefinir y eliminar métodos en tiempo de ejecución. El problema del círculo-elipse se resuelve fácilmente en CLOS, y la mayoría de los patrones de diseño de programación orientada a objetos desaparecen o son cualitativamente más simples. [2]

CLOS no es un lenguaje prototipo : las clases deben definirse antes de que los objetos puedan instanciarse como miembros de esa clase.

Protocolo de metaobjetos

Además del estándar ANSI Common Lisp, existe una extensión ampliamente implementada de CLOS llamada Metaobject Protocol (MOP). El MOP define una interfaz estándar para los fundamentos de la implementación de CLOS, tratando las clases, las descripciones de ranuras, las funciones genéricas y los métodos en sí mismos como instancias de metaclases , y permite la definición de nuevas metaclases y la modificación de todo el comportamiento de CLOS. La flexibilidad del CLOS MOP prefigura la programación orientada a aspectos , que fue desarrollada posteriormente por algunos de los mismos ingenieros, como Gregor Kiczales . El MOP define el comportamiento de todo el sistema de objetos mediante un conjunto de protocolos. Estos se definen en términos de CLOS. Por lo tanto, es posible crear nuevos sistemas de objetos ampliando o cambiando la funcionalidad proporcionada por CLOS. El libro The Art of the Metaobject Protocol describe el uso y la implementación del CLOS MOP.

Las distintas implementaciones de Common Lisp ofrecen un soporte ligeramente diferente para el Protocolo de metaobjetos. El proyecto Closer [3] tiene como objetivo proporcionar las funciones faltantes.

Influencias de sistemas de objetos más antiguos basados ​​en Lisp

Flavors (y su sucesor New Flavors) fue el sistema de objetos de la MIT Lisp Machine . Gran parte de los sistemas operativos de la Lisp Machine y muchas aplicaciones para ella utilizan Flavors o New Flavors. Flavors introdujo la herencia múltiple y los mixins , entre otras características. Flavors está en su mayor parte obsoleto, aunque existen implementaciones para Common Lisp. Flavors utilizaba el paradigma de paso de mensajes. New Flavors introdujo funciones genéricas.

CommonLoops fue el sucesor de LOOPS (de Xerox Interlisp -D). CommonLoops se implementó para Common Lisp. Una implementación portátil llamada Portable CommonLoops (PCL) fue la primera implementación de CLOS. PCL se ha adaptado ampliamente y aún proporciona la base para la implementación de CLOS de varias implementaciones de Common Lisp . PCL se implementa principalmente en Common Lisp portátil con solo unas pocas partes dependientes del sistema.

CLOS en otros lenguajes de programación

Debido a la potencia y expresividad de CLOS, así como a la disponibilidad histórica de Tiny CLOS (una implementación de CLOS portable y simplificada escrita por Gregor Kiczales para usar con Scheme), los sistemas de objetos basados ​​en MOP similares a CLOS se han convertido en la norma de facto en la mayoría de las implementaciones de dialectos Lisp, y también han encontrado su camino hacia las facilidades OOP de algunos otros lenguajes :

Lectura adicional

Referencias

  1. ^ "CLOS es un estándar. Varios proveedores suministran CLOS. CLOS (o partes de él) se utiliza para añadir orientación a objetos a otros dialectos de Lisp, como EuLisp o Emacs Lisp". p. 110 de Veitch 1998
  2. ^ En las diapositivas Patrones de diseño en lenguajes dinámicos, Peter Norvig presenta sus hallazgos de que 16 de 23 patrones de diseño tomados de varios libros de texto son "invisibles o más simples" en Dylan o Common Lisp que en C++.
  3. ^ Proyecto Más Cercano: Más Cercano al MOP
  4. ^ Deniau, Laurent (12 de marzo de 2010). El sistema de objetos C: uso de C como lenguaje orientado a objetos de alto nivel (PDF) . arXiv : 1003.2547 . CiteSeerX 10.1.1.763.7946 . Consultado el 17 de marzo de 2022 . 
  5. ^ Extensión orientada a objetos de Dynace para C
  6. ^ Newton, Jim; Rhodes, Christophe (28 de noviembre de 2008). "Especialistas personalizados en Object-Oriented Lisp". Journal of Universal Computer Science . 14 (20): 3370–3388. CiteSeerX 10.1.1.523.2413 . doi : 10.3217/jucs-014-20-3370 . S2CID  12032836 . Consultado el 17 de marzo de 2022 . 
  7. ^ Tiny CLOS, desarrollado por Gregor Kiczales

Literatura