En ingeniería de software, un tipo abstracto es un tipo en un sistema de tipo nominativo que es declarado por el programador, y que tiene la propiedad de no contener miembros que no sean miembros de algún subtipo declarado. Según el paradigma de programación orientado a objetos, los tipos abstractos se implementan bajo nombres como clases base abstractas, interfaces, rasgos (en inglés, traits), mixins, sabores (en inglés, flavors) o roles.
- Este artículo trata sobre tipos sin miembros directos; ver también Tipo de dato abstracto.
Las clases abstractas pueden ser creadas, indicadas o simuladas de diversas formas:
- Usando la palabra clave abstract en la definición de la clase, como en Java.
- Incluyendo, en la definición de la clase, uno o más métodos abstractos (llamados funciones virtuales puras en C++; métodos que la clase está declarada para aceptar como parte de su protocolo, pero para los que no se proporciona implementación.
- Por herencia de un tipo abstracto, y no sobrescribiendo todas las características necesarias para completar la definición de la clase que falten.
- En muchos lenguajes tipados dinámicamente como Smalltalk, cualquier clase que envíe un método particular a this, pero no implemente ese método, puede ser considerada abstracta. Sin embargo, en muchos lenguajes de este tipo, los posibles errores no son detectados hasta que se usa la clase, y el mensaje envía resultados en un error como doesNotUnderstand. más o menos
Los tipos abstractos son una característica importante en lenguajes orientados a objetos tipados estáticamente. No se dan en lenguajes sin subtipos. Muchos lenguajes tipados dinámicamente no tienen características equivalentes, aunque el uso de duck typing hace los tipos abstractos innecesarios; sin embargo, algunos lenguajes modernos tipados dinámicamente tienen traits.
Muchos autores argumentan que las clases deberían ser clases hoja (sin subtipos), o si no, deberían ser abstractas.
Los tipos abstractos son útiles en que pueden ser utilizados para definir y establecer un protocolo; un conjunto de operaciones que todos los objetos que implementen el protocolo deben soportar. El hecho de que muchos lenguajes no permitan la instanciación de tipos abstractos (y fuercen a los subtipos a implementar todas las funcionalidades necesarias) asegura todavía más la corrección del programa.
Hay varios mecanismos para crear tipos abstractos, que varían según sus capacidades.
- Clases base abstractas completas. Son las clases tanto explícitamente declaradas como abstractas como las que contienen métodos abstractos (no implementados). Excepto la capacidad de instanciación, tienen las mismas capacidades que una clase o tipo concreto. Los tipos abstractos completos estaban presentes en las primeras versiones de C++, y la clase base abstracta permanece como la única construcción del lenguaje para generar tipos abstractos en C++.
- Nota: Debido a problemas técnicos con la herencia múltiple en C++ y otros lenguajes; muchos lenguajes orientados a objetos intentaron restringir la herencia a una sola clase base directa. Para soportar múltiple subtipado, varios lenguajes añadieron otras características que podían ser usadas para crear tipos abstractos, pero con menos potencia que clases desarrolladas del todo.
- Common Lisp Object System (CLOS) incluye mixins, basados en el sistema Flavors desarrollado por David Moon para Lisp Machine Lisp. CLOS utiliza funciones genéricas, definidas aparte de las clases, en lugar de funciones miembro definidas en la clase.
- Java incluye interfaces, un tipo abstracto que puede contener cabeceras de métodos y constantes (variables finales), pero no implementación de métodos o miembros de datos no-finales. Las clases de Java pueden "implementar" múltiples interfaces. Una clase abstracta en Java puede implementar interfaces y definir algunas cabeceras de método al tiempo que mantiene otros métodos abstractos con la palabra clave "abstract". Este tipo de plantilla abstracta puede heredar de una clase concreta.
- Traits son un enfoque más reciente al problema, que se puede encontrar en Scala y Perl 6 (llamados roles), y propuesto como extensión a Smalltalk (donde fue desarrollada la implementación original). Los traits no están restringidos en lo que incluyen en su definición, y múltiples traits pueden ser pueden componer la definición de una clase. Sin embargo, las reglas de composición para traits son diferentes de las de la herencia estándar, para evitar las dificultades semánticas a menudo asociadas con la herencia múltiple.
- Types and Programming Languages by Benjamin Pierce (MIT Press 2002) (en inglés)
- More Effective C++: 35 New Ways to Improve Your Programs and Designs by Scott Meyers (1995) ISBN 0-201-63371-X (en inglés)
- Traits: Composable Units of Behavior by Nathanael Schärli, Stéphane Ducasse, Oscar Nierstrasz and Andrew Black (en inglés)