¿Cuál es la diferencia entre clase abstracta e interfaz en Python?
fuente
¿Cuál es la diferencia entre clase abstracta e interfaz en Python?
Lo que verá a veces es lo siguiente:
class Abstract1( object ):
"""Some description that tells you it's abstract,
often listing the methods you're expected to supply."""
def aMethod( self ):
raise NotImplementedError( "Should have implemented this" )
Debido a que Python no tiene (y no necesita) un contrato de interfaz formal, la distinción de estilo Java entre abstracción e interfaz no existe. Si alguien se esfuerza por definir una interfaz formal, también será una clase abstracta. Las únicas diferencias estarían en la intención declarada en la cadena de documentación.
Y la diferencia entre el resumen y la interfaz es una cosa desgarradora cuando tienes que escribir en un pato.
Java usa interfaces porque no tiene herencia múltiple.
Debido a que Python tiene herencia múltiple, también puede ver algo como esto
class SomeAbstraction( object ):
pass # lots of stuff - but missing something
class Mixin1( object ):
def something( self ):
pass # one implementation
class Mixin2( object ):
def something( self ):
pass # another
class Concrete1( SomeAbstraction, Mixin1 ):
pass
class Concrete2( SomeAbstraction, Mixin2 ):
pass
Esto utiliza una especie de superclase abstracta con mixins para crear subclases concretas que son disjuntas.
NotImplementedError("Class %s doesn't implement aMethod()" % (self.__class__.__name__))
es un mensaje de error más informativo :)Una interfaz, para un objeto, es un conjunto de métodos y atributos en ese objeto.
En Python, podemos usar una clase base abstracta para definir y aplicar una interfaz.
Usando una clase base abstracta
Por ejemplo, supongamos que queremos usar una de las clases base abstractas del
collections
módulo:Si intentamos usarlo, obtenemos un
TypeError
porque la clase que creamos no admite el comportamiento esperado de los conjuntos:Por lo tanto estamos obligados a implementar al menos
__contains__
,__iter__
y__len__
. Usemos este ejemplo de implementación de la documentación :Implementación: creación de una clase base abstracta
Podemos crear nuestra propia Clase base abstracta configurando la metaclase
abc.ABCMeta
y utilizando elabc.abstractmethod
decorador en métodos relevantes. La metaclase agregará las funciones decoradas al__abstractmethods__
atributo, evitando la creación de instancias hasta que se definan.Por ejemplo, "effable" se define como algo que se puede expresar en palabras. Digamos que queremos definir una clase base abstracta que sea effable, en Python 2:
O en Python 3, con el ligero cambio en la declaración de metaclase:
Ahora, si intentamos crear un objeto effable sin implementar la interfaz:
e intentar instanciarlo:
Nos dicen que no hemos terminado el trabajo.
Ahora si cumplimos proporcionando la interfaz esperada:
entonces podemos usar la versión concreta de la clase derivada de la abstracta:
Hay otras cosas que podríamos hacer con esto, como registrar subclases virtuales que ya implementan estas interfaces, pero creo que eso está más allá del alcance de esta pregunta.
abc
Sin embargo, los otros métodos demostrados aquí tendrían que adaptar este método usando el módulo para hacerlo.Conclusión
Hemos demostrado que la creación de una clase base abstracta define interfaces para objetos personalizados en Python.
fuente
Python> = 2.6 tiene clases base abstractas .
También está el módulo Zope Interface , que es utilizado por proyectos fuera de zope, como twisted. No estoy realmente familiarizado con eso, pero hay una página wiki aquí que podría ayudar.
En general, no necesita el concepto de clases abstractas o interfaces en python (editado - vea la respuesta de S.Lott para más detalles).
fuente
Python realmente no tiene ninguno de los dos conceptos.
Utiliza la escritura de pato, lo que eliminó la necesidad de interfaces (al menos para la computadora :-))
Python <= 2.5: las clases base obviamente existen, pero no existe una forma explícita de marcar un método como 'virtual puro', por lo que la clase no es realmente abstracta.
Python> = 2.6: existen clases base abstractas ( http://docs.python.org/library/abc.html ). Y le permite especificar métodos que deben implementarse en subclases. No me gusta mucho la sintaxis, pero la función está ahí. La mayoría de las veces, probablemente sea mejor usar la escritura de pato desde el lado del cliente 'usar'.
fuente
En una forma más básica de explicar: una interfaz es como una bandeja de panecillos vacía. Es un archivo de clase con un conjunto de definiciones de métodos que no tienen código.
Una clase abstracta es lo mismo, pero no todas las funciones deben estar vacías. Algunos pueden tener código. No está estrictamente vacío.
Por qué diferenciar: no hay mucha diferencia práctica en Python, pero a nivel de planificación para un proyecto grande, podría ser más común hablar de interfaces, ya que no hay código. Especialmente si está trabajando con programadores de Java que están acostumbrados al término.
fuente
En general, las interfaces se usan solo en idiomas que usan el modelo de clase de herencia única. En estos lenguajes de herencia única, las interfaces se usan típicamente si alguna clase podría usar un método o conjunto de métodos en particular. También en estos lenguajes de herencia única, las clases abstractas se usan para tener variables de clase definidas además de ninguno o más métodos, o para explotar el modelo de herencia única para limitar el rango de clases que podrían usar un conjunto de métodos.
Los lenguajes que admiten el modelo de herencia múltiple tienden a usar solo clases o clases base abstractas y no interfaces. Dado que Python admite la herencia múltiple, no usa interfaces y querrás usar clases base o clases base abstractas.
http://docs.python.org/library/abc.html
fuente
Las clases abstractas son clases que contienen uno o más métodos abstractos. Junto con los métodos abstractos, las clases abstractas pueden tener métodos estáticos, de clase y de instancia. Pero en el caso de la interfaz, solo tendrá métodos abstractos, no otros. Por lo tanto, no es obligatorio heredar la clase abstracta, pero sí es obligatorio heredar la interfaz.
fuente
Para completar, debemos mencionar PEP3119 donde se introdujo ABC y se comparó con las interfaces, y el Talin original comentario .
La clase abstracta no es la interfaz perfecta:
Pero si considera escribirlo a su manera:
te darás cuenta rápidamente de que estás inventando la rueda para lograr
abc.ABCMeta
abc.ABCMeta
se propuso como una adición útil de la funcionalidad de la interfaz que falta, y eso es bastante justo en un lenguaje como python.Ciertamente, se pudo mejorar mejor al escribir la versión 3, y agregar una nueva sintaxis y un concepto de interfaz inmutable ...
Conclusión:
fuente