1. Introducción CLOS: Common Lisp Object Systems. Supone la incorporación de la programación orientada a objeto al lenguaje Common-lisp Integración de la programación funcional y la programación orientada a objeto. Como resultado del proceso de estan-darización del Common LISP se incorpora CLOS.
Introducción Objetivos en el diseño de CLOS: (Sonya E., Keen 89. “Object Oriented programming in Common Lisp. A programmers guide to CLOS.”) Extensión del estándar Common Lisp que inclu-ya aspectos del paradigma de POO. La interfaz que ofrezca CLOS a los programa-dores debe ser sencillo y potente: El programa se estructura reflejando la estruc- tura del sistema que se está modelando. Los usuarios utilizan un programa a través de una interfaz bien definida. Utilización de las clases como elemento básico de modularidad. CLOS debe ser diseñado como un protocolo extensible. El “Meta Object protocol” permite adaptar el lenguaje. CLOS no fuerza la utilización de un estilo orien-tado a objeto.
2. Elementos CLOS(Interfaz del Programador) 2.1. Clases e Instancias: Una clase define un nuevo TIPO Common Lisp: Las instancias de una clase tienen la misma estructura, comportamiento y son del mismo tipo. Además cada instancia tiene una identidad separada. (DEFCLASS nombre-clase (nombres-superclases)* (descripción-slots) opciones-clase*) Descripción-slots= (nombre-slot opciones-slot*)
Cada opción es una “Keyword”: :ACCESSOR nombre-función :INITFORM expresión :INITARG symbol
Clases e Instancias Comparación con DEFSTRUCT (DEFSTRUCT persona (nombre Juan) (edad 26)) DEFSTRUCT define automáticamente * Los atributos con los valores por defecto * funciones de acceso como PERSONA-NOMBRE para leer y modificar el valor del atributo y la función MAKE-PERSONA para crear instancias e inicializar los valores con Keywords :
(MAKE-PERSONA :nombre ‘Pepe :edad 3) (DEFCLASS persona () ((nombre :accessor nombre-persona :initform Juan :initarg :nombre) (edad :accessor edad-persona :initform 26 :initarg :edad))) DEFCLASS define * Los atributos con los valores por defecto en :initform * funciones de acceso como indicadas en :accesor * keywords para inicializar la instancia en :initarg
(MAKE-INSTANCE ‘persona :nombre ‘Pepe :edad 3)
¿Porqué definir tipos mediante Clases? Las clases permiten definir TADs, separan-do claramente la interfaz de un objeto de la implementación. El mecanismo que permite definir la interfaz de una clase son las FUNCIONES GENERICAS CLOS permite la definición de una clase a partir de otras clases mediante herencia múl-tiple. Las clases HEREDAN tanto la estructura (atributos) como el comportamiento (la interfaz y la implementación) de las clases padres (*). (Gp:) OOP = TADs +Herencia
(*) Defstruct permite definir una nueva estructura a partir de otra estructura (sólo una) definida previa- mente. Sólo se heredan las funciones de acceso a los atributos, y no es posible especializar dichas funciones. Una estructura no encapsula el compor- tamiento de un TAD.
Funciones Genéricas y Métodos 2.2. Las funciones genéricas son funciones que se comportan de diferente manera dependiendo del tipo e identidad de los argumentos. – Ejemplo con funciones ordinarias:
(defun tipo-de (x) (typecase x (number (format T "~% ~a es un numero"x)) (list (format T "~% ~a es una lista"x)) (symbol (format T "~% ~a es un simbolo"x)))) – Ejemplo con funciones genéricas:
(defgeneric tipo-de (x) (:documentation "Indica el tipo de un objeto"))
(defmethod tipo-de ((x number)) (format T "~% ~a es un numero"x))
(defmethod tipo-de ((x list)) (format T "~% ~a es una lista" x))
(defmethod tipo-de ((x symbol)) (format T "~% ~a es un simbolo" x))
Funciones Genéricas y Métodos Sin funciones genéricas hay que localizar y modi- ficar las funciones que se vean afectadas por la introducción del nuevo tipo (utilización de “cond”, typecase”, “case”) Con funciones genéricas es fácil contemplar el comportamiento de una función para nuevos tipos
(DEFCLASS persona () ((nombre :accessor nombre-persona :initform 'Juan :initarg :nombre) (edad :accessor edad-persona :initform 26 :initarg :edad)))
(defmethod tipo-de ((x persona)) (format T "~% ~a es una persona" x))
(Gp:) ? (setf pepe (make-instance 'persona :nombre 'pepe :edad 22)) # ? (tipo-de pepe) # es una persona NIL ?
Funciones Genericas Para el usuario, las funciones genéricas son exáctemente igual a una función ordinaria: La sintáxis para invocar ambas es exactemente igual. La semántica es diferente: Una función ordinaria especifica el interfaz y la implementación de la operación: (Gp:) valores (Gp:) efectos laterales
Implementación e interfaz argumentos (defun nombre lambda-list {form}* ) Función Lisp ordinaria
Funciones genéricas Una función genérica sólo especifica el interfaz. La implementación se distribuye en un conjunto de métodos: (defgeneric nombre lambda-list ) (Gp:) interfaz (Gp:) argumentos
(Gp:) valores (Gp:) efectos laterales
(Gp:) valores (Gp:) efectos laterales
(Gp:) valores (Gp:) efectos laterales
Implementaciones Función Genérica
Página siguiente |