2010-03-05 21 views
14

Digamos que tengo class, que usa alguna funcionalidad de dict. Solía ​​componer un objeto dict dentro y proporcionar algún acceso desde el exterior, pero recientemente pensé en simplemente heredar dict y agregar algunos atributos y métodos que podría necesitar. ¿Es una buena forma de ir, o debo apegarme a la composición?python: heredando o composición

Respuesta

13

La herencia se abusa muy a menudo. A menos que su clase esté destinada a ser usada como un diccionario genérico con funcionalidad adicional, diría que la composición es el camino a seguir.

Guardar llamadas de reenvío generalmente no es una razón suficiente para elegir la herencia.

Del libro de patrones de diseño: composición de objetos

favor sobre la herencia de clases

Lo ideal es que no deberían tener que crear nuevos componentes para lograr la reutilización. Usted debe ser capaz de obtener todas las funcionalidades que necesita ensamblando componentes existentes a través del objeto composición. Pero esto rara vez es el caso , porque el conjunto de componentes disponibles nunca es lo suficientemente rico como en la práctica. La reutilización por herencia facilita la creación de nuevos componentes que se pueden componer con los antiguos. Herencia y composición de objetos así trabajan juntos.

Sin embargo, nuestra experiencia es que los diseñadores herencia uso excesivo como una técnica de reutilización y diseños son a menudo hizo más reutilizables (y más simple) por dependiendo más de la composición de objetos."

El texto completo está aquí: http://blog.platinumsolutions.com/node/129

+3

Recuerde que Python es extremadamente flexible, la composición de los objetos es excelente, pero si solo está asignando uno a uno a otro objeto, la herencia es el camino a seguir. – voyager

+3

No creo que tenga nada que ver con que Python sea flexible, es un problema de diseño. Si está mapeando todos los métodos de un objeto para el otro, entonces probablemente esté construyendo un diccionario: use inheritance. Pero cuando el póster original escribe "Tengo clase, que usa alguna funcionalidad de dict", insinúa el hecho de que la clase no debe usarse como diccionario. –

+0

El enlace a platinumsolutions ya no funciona ... es posible que desee editar ... – unclejamil

3

Ambos son buenos, pero preferiría heredar, ya que significará menos código (que siempre es bueno, siempre y cuando sea legible).

Dive into Python has a very relevant example.

En Python 2.2 y anteriores, no se podía crear una subclase de ins integrados directamente, por lo que tenía para usar la composición.

class FileInfo(dict):     
    "store file metadata" 
    def __init__(self, filename=None): 
     self["name"] = filename 
  1. La primera diferencia es que no es necesario importar el módulo UserDict, ya que dict es un tipo de datos incorporado y está siempre disponible. El segundo es que estás heredando de dict directamente, en lugar de desde UserDict.UserDict.
  2. La tercera diferencia es sutil pero importante. Debido a la forma en que UserDict funciona internamente, se requiere llamar manualmente al método __init__ para inicializar correctamente sus estructuras internas de datos. dict no funciona así; no es un contenedor, y no requiere una inicialización explícita.
3

Realmente hay que sopesar el coste y el alcance de lo que estamos tratando de hacer Heredar de dict porque desea un comportamiento similar al diccionario es rápida. y fácil pero propenso a limitaciones tales como hacer que los objetos creados desde su clase sean indescompensables.

Entonces, por ejemplo, si va a necesitar serializar (es decir, pickle) los objetos, pero también desea un comportamiento tipo diccionario, entonces obviamente no puedes heredar directamente desde dict y deberá redactar las partes de la funcionalidad que desee para que eso suceda.

3

¿Debería isinstance(my_object, dict) devolver verdadero o falso? En otras palabras, si accidentalmente le das uno de los objetos a algo que quiere un dict, ¿debería tratar alegremente de usarlo como dict? Probablemente no, así que usa la composición.

+0

Ayudar a la gente a verificar tipos no es necesariamente algo bueno. –

+0

La comprobación de tipos tiene su lugar. Por ejemplo, si tiene una bonita función de impresora que entienda los dicts, probablemente no desee que imprima su objeto mejorado como si fuera un dict. Tampoco querrías usar la alternativa sin verificación de tipo: monje parcheo dict. –