Clases abstractas en Python

Python de forma nativa no soporta clases abstractas, pero eso no significa que no existan. A partir de la versión 2.6, Python trae el módulo abc (abstract base classes) de acuerdo a PEP 3119, que consigue emular la abstracción de clases mediante metaclases y decoradores Python.

python abstract class

Metaclases

Un buen artículo muy recomendable que consigue explicar el mundillo de las metaclases sin pegarse un tiro en la cabeza, es este de crysol Ahí va la virgen! Metaclases! (con Python). Pero para hacerse una idea, diremos que una metaclase es una clase cuyas instancias son clases en lugar de objetos.

Es decir, si para construir un objeto usas una clase, para construir una clase usas una metaclase. Es importante entender que en Python todo es un objeto (incluso las clases, los modulos, los tipos de datos, etc..) y por lo tanto las clases, al ser objetos, son instancias de una metaclase.

En el caso que nos ocupa, es interesante porque permite modificar el comportamiento o características de una clase en el momento de su creación.


Decoradores

Respecto a los decoradores pues prefiero recomendaros un artículo de la casa ;-) Decoradores Python. A modo de resumen diremos que un decorador Python permite añadir funcionalidad extra a una función mediante un wrapper (envoltorio).


Clases abstractas en Python

Para empezar. Definiremos un método abstracto mediante el uso del decorador @abstractmethod. Al instanciar la clase… ¡Sorpresa! ha funcionado. Python no se queja.

Para que el invento funcione, la clase Vehicle tiene que heredar de la metaclase ACBMeta. Con un poco de ‘azucar sintáctico’ (¿what?) mediante __metaclass__ es fácil. Ahora Python hace lo esperado, se queja porque no es posible instanciar una clase con métodos abstractos.

Para curiosos. En el repositorio oficial está la implementación de la metaclase ABCMeta. Ahora vamos a crear una clase Car que herede de Vehicle y que sobreescriba el método abstracto.

Como curiosidad, podemos hacer ‘trampas’ e invocar al método abstracto mediante el uso de super().

Con el decorador @abstractproperty podemos crear propiedades abstractas. Aquí un ejemplo.

El anterior ejemplo definimos una propiedad de lectura. También es posible crear propiedades abstractas de lectura y escritura (getter & setter) pero esto solo es posible hacerlo sin ‘azúcar sintáctico’

Esta entrada fue publicada en Sin categoría y etiquetada . Guarda el enlace permanente.

Los comentarios están cerrados.