2012-01-04 10 views
7

tengo un siguiente modelo y la clase base abstractaUn modelo de Django que las subclases de un ABC, da un conflicto metaclase

import abc 
from django.db import models 


class AbstractBase(): 
    __metaclass__ = abc.ABCMeta 

    @abc.abstractmethod 
    def my_method(self): 
     return 


class MyModel(models.Model, AbstractBase): 
    @abc.abstractmethod 
    def my_method(self): 
     return 1 

Pero estoy consiguiendo el error siguiente.

conflicto metaclase: la metaclase de una clase derivada debe ser una (no estricto) subclase de los metaclases de todas sus bases

Creo que el problema aquí es (como se describe aquí http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/) que dos clases base tienen dos metaclases diferentes, por lo que python no puede decidir qué metaclase usar para el objeto hijo.

Con el fin de resolver este quité inheritence múltiples y el uso siguiente método de registro para registrar clase hija

abc.register(Child) 

Pero realmente no me gusta este enfoque ya que parece que el mono parches.

¿Hay alguna otra forma de resolver este problema?

Intento asignar la metaclase del modelo a Child explícitamente pero no funcionó. No estoy buscando una manera de resolverlo escribiendo código. Creo que esto debe resolverse cambiando mi estructura de clase.

+0

Creo que vas a tener que crear una nueva metaclase que haga las cosas de django y abc, probablemente llamando a sus respectivas metaclases en orden, tal vez usando herencia. – cha0site

+0

No hay nada de hackish en usar el método abs.register: está diseñado exactamente para estos casos. Por cierto, la manera de pensar de Python está hecha, por lo que rara vez deberías necesitar interfaces y tal vez, ¿estás demasiado limitado por la manera en que se hacen las cosas en los lenguajes estáticos? – jsbueno

+0

@jsbueno - Puede que tengas razón, pero necesitaré implementar la funcionalidad de la interfaz de alguna manera. Aquí hay un ejemplo de implantación: https://gist.github.com/1559689. ¿Hay una mejor manera de implementar esta funcionalidad en python? – yilmazhuseyin

Respuesta

2

Además de crear un nuevo metaclase que hereda de ambos ABCMeta y ModelBase, o hacer ABCMeta Heredar del ModelBase, no hay mucho que puede hacer.

Sin embargo, ¿podría ser apropiado un patrón de registro diferente? Tal vez algo así como contrib.admin.autodiscover? ¿O un decorador de clase? O un bucle en la parte inferior del archivo .py que llama al register en las clases correspondientes (por ejemplo, for var in globals().values(): if isinstance(var, type) and issubclass(var, AbastractBase): register(var))?

Editar: D'oh. Supuse que ABCMeta era un ejemplo, no ABCMeta. Eso es lo que obtengo al navegar por StackOverflow con muy poco sueño.

+0

Mi conclusión sobre esto es Si estoy usando abc como interfaz, debería usar abc.register. Realmente creo que debería haber una mejor manera de implementar una interfaz (http://www.python.org/dev/peps/pep-0245/). Sin ellos, las características de Python me parecen muy débiles. – yilmazhuseyin

+3

Si siente que esto "debilita el PyO de Python", entonces podría sugerir humildemente que su comprensión de los "requisitos para OO fuerte" difiere drásticamente de los de los diseñadores de Python (o que accidentalmente escribió "oo" cuando quería escribir "comprobación de tipo estático"?) –

Cuestiones relacionadas