2008-11-13 19 views
6

Quiero analizar un archivo Apache access.log con un programa de python de una cierta manera, y aunque soy completamente nuevo en la programación orientada a objetos, quiero comenzar a hacerlo ahora.¿Es correcto heredar de las clases incorporadas?

Voy a crear una clase ApacheAccessLog, y la única cosa que puedo imaginar ahora, se hará a continuación es 'readline' método. ¿Es convencionalmente correcto heredar de la clase de archivo incorporado en este caso, por lo que la clase se comportará como una instancia de la clase del archivo, o no? ¿Cuál es la mejor manera de hacer eso?

Respuesta

15

En este caso utilizaría delegación en lugar de herencia. Significa que su clase debe contener el objeto de archivo como un atributo e invocar un método readline en él. Podría pasar un objeto de archivo en el constructor de la clase de registrador.

Hay al menos dos razones para esto:

  1. Delegación reduce el acoplamiento, por ejemplo, en lugar del archivo de objetos se puede utilizar cualquier otro objeto que implementa un readline método (pato escribir es muy útil aquí) .
  2. Al heredar del archivo, la interfaz pública de su clase se vuelve innecesariamente amplia. Incluye todos los métodos definidos en el archivo, incluso si estos métodos no tienen sentido en el caso de un registro de Apache.
1

Es perfectamente aceptable heredar de una clase incorporada. En este caso, diría que tienes razón en el dinero.
El registro "es un" archivo por lo que dice que la herencia está bien ..

Regla general.
El perro "es un" n animal, por lo tanto, hereda de un animal.
El propietario "tiene un" n animal, por lo tanto, no hereda de un animal.

1

Aunque en algunos casos es útil heredar de las construcciones internas, la verdadera pregunta aquí es qué quiere hacer con la salida y cuál es su diseño de imagen grande. Normalmente escribo un lector (que usa un objeto de archivo) y escupo cualquier clase de datos que necesito para contener la información que acabo de leer. Entonces es fácil diseñar esa clase de datos para encajar con el resto de mi diseño.

1

Debe ser bastante seguro heredar de una clase "incorporada", ya que las modificaciones posteriores a estas clases generalmente serán compatibles con la versión actual.

Sin embargo, debe pensar seriamente si realmente desea vincular su clase a la funcionalidad adicional proporcionada por la clase integrada. Como se menciona en otra respuesta, debería considerar (quizás incluso prefiera) usar la delegación .

Como un ejemplo de por qué para evitar la herencia si no lo necesita se puede ver en la clasejava.util.Stack. A medida que se extiende Vector, hereda todos de los métodos en Vector. La mayoría de estos métodos infringen el contrato implícito en Stack, p. LIFO. Hubiera sido mucho mejor implementar Stack usando un Vector internamente, solo exponiendo los métodos de Stack como la API.Entonces habría sido fácil cambiar la implementación a ArrayList u otra cosa más tarde, ninguna de las cuales es posible ahora debido a la herencia.

6

Vengo de un entorno Java pero estoy bastante seguro de que se aplicarán los mismos principios en Python. Como regla general, debe nunca heredar de una clase cuya implementación no comprenda ni controle a menos que dicha clase se haya diseñado específicamente para herencia. Si ha sido diseñado de esta manera, debe describir esto claramente en su documentación.

La razón de esto es que la herencia puede potencialmente vincularlo a los detalles de implementación de la clase que está heredando.

Para usar un ejemplo del libro de Josh Bloch 'Effective Java'

Si nos vamos a extender la clase clase ArrayList con el fin de ser capaz de contar el número de elementos que se agregaron a la misma durante su tiempo de vida (no necesariamente el número que contiene actualmente), podemos sentirnos tentados de escribir algo como esto.

public class CountingList extends ArrayList { 
    int counter = 0; 

    public void add(Object o) { 
     counter++; 
     super.add(0); 
    } 

    public void addAll(Collection c) { 
     count += c.size(); 
     super.addAll(c); 
    } 

    // Etc. 
} 

Ahora esta extensión parece que sería contar con precisión el número de elementos que se agregaron a la lista, pero, de hecho, puede que no. Si ArrayList ha implementado addAll iterando sobre el Collection provisto y llamando a su método de interfaz addAll para cada elemento, contaremos dos veces cada elemento agregado mediante el método addAll. Ahora el comportamiento de nuestra clase depende de los detalles de implementación de ArrayList. Por supuesto, además de la desventaja de no poder utilizar otras implementaciones de List con nuestra clase CountingList. Además de las desventajas de heredar de una clase concreta que se discutieron anteriormente.

Tengo entendido que Python utiliza un mecanismo de envío de métodos similar (si no idéntico) a Java y, por lo tanto, estará sujeto a las mismas limitaciones. Si alguien pudiera dar un ejemplo en Python, estoy seguro de que sería aún más útil.

0

Parece que ha encontrado su respuesta que en este caso la delegación es la mejor estrategia. Sin embargo, me gustaría añadir que, salvo la delegación, no hay nada de malo en extender una clase incorporada, particularmente si su alternativa, según el idioma, es "parche de monos" (ver http://en.wikipedia.org/wiki/Monkey_patch)

Cuestiones relacionadas