2010-06-30 12 views
6

Puede alguien explicar desventaja de herencia en Javadesventajas de la herencia en Java

+0

no java perse, si alguien explica los inconvenientes de la herencia ... que es una buena lectura :) –

+3

¿Puedes ... contener un poco el alcance de tu pregunta? ¿Hay problemas específicos que te preocupan? Por ejemplo, herencia individual vs. múltiple, o herencia de clase vs. prototípica, o ... (¿O es esta tarea?) –

+0

desventaja en comparación con la herencia en otros idiomas, o desventajas de herencia en comparación con la composición, por ejemplo? –

Respuesta

9

es probable que desee leer:

eficaz de Java ™, segunda edición Por: Joshua Bloch

Capítulo 4. Clases y Interfaces

artículo 16: composición favor sobre la herencia

artículo 17: Diseño y doc ument para la herencia o de lo contrario lo prohíbe

Artículo 18: Prefiero interfaces para las clases abstractas

5

Tome un botín en el artículo de Allen Holub en JavaWorld titulado Why extends is evil. Discute cosas como el acoplamiento cerrado y el problema fragile base class.

+0

El artículo no evita la herencia per se, solo extiende las clases base concretas. –

1

Preferimos la composición sobre la herencia porque cuando agregamos (particularmente) o cambiamos la funcionalidad por subclases, juntamos esa nueva funcionalidad a la clase, por lo que en cualquier lugar que necesitemos la nueva funcionalidad, necesitamos esa clase. Eso se extiende incluso a otras subclases, y con el modelo de herencia única de Java, si tenemos dos nuevos bits de funcionalidad que queremos en otra clase más, no hay una forma (simple) de incorporar ambos bits, si cada uno está en una subclase separada de el antepasado original.

En comparación, si ampliamos la funcionalidad a través de la composición, cualquier clase, dentro o fuera de nuestra jerarquía existente, puede incorporarlo simplemente incluyendo la pequeña clase que tiene la nueva función. Es más simple, más limpio, más reutilizable y más fácil de leer.

La herencia tiene su lugar, pero no es la herramienta adecuada para muchos, muchos trabajos.

3

A menos que su clase esté diseñada para herencia, debe hacerse definitiva. Debe tener mucho cuidado para asegurarse de comprender cómo se anularán los métodos en una subclase que no fue diseñada para la función de herencia, a fin de comprender cómo modificarlos.

Un ejemplo concreto:

Considere usted tiene una clase que maneja una lista de nombres ...

public class MyNameManager { 
    private List<String> numbers = new LinkedList<String>(); 

    public void add(String value) { 
    numbers.add(value); 
    } 

    public void addAll(Collection<String> values) { 
    for(String value : values) { 
     add(value); 
    } 
    } 

    public void remove(String value) { //... } 

    //... 
} 

Ahora dicen que desea crear una nueva subclase que también cuenta el número total de de veces un nombre se agrega a la lista, así:

public class MyCountingNameManager extends MyNameManager { 
    private int count = 0; 

    @Override 
    protected void addAll(Collection<String> values) { 
    count += values.size(); 
    super.addAll(values); 
    } 

    @Override 
    protected void add(String value) { 
    count += 1; 
    super.add(value); 
    } 
} 

Parece bastante sencillo, ¿no? Pero considere el resultado de lo siguiente:

MyCountingNameManager m = new MyCountingNameManager(); 
m.add("bob"); 
m.add("Sally"); 

El conteo ahora es 2 y todo está bien. Pero si tuviéramos que hacer lo siguiente:

List<String> family = new List<String>(); 
family.add("mom"); 
family.add("dad"); 
family.add("brother"); 

MyCountingNameManager m = new MyCountingNameManager(); 
m.add(family); 

El recuento es ahora de 6 años, no el 3 lo que probablemente esperan. Esto se debe a que la llamada al addAll agrega el tamaño de la Colección de valores (que es 3) al conteo, y luego llama al método super.addAll para realizar el procesamiento real.super.addAll itera la colección y llama al método add para cada valor. Pero dado que estamos trabajando en un MyCountingNameManager y no en a MyNameManager, se llama al método Oreemplazado en la subclase cada vez. ¡El método MyCountingNameManager.add que se ejecuta también incrementa el conteo! ¡Entonces el resultado es que cada nombre se cuenta dos veces!

Creo que este ejemplo proviene de Java efectivo. Definitivamente debe encontrar una copia y leer los elementos enumerados en la respuesta de Viele para una comprensión más profunda de algunos casos en los que la herencia no se ajusta bien.