2010-03-03 15 views
8

Bueno, iba a preguntar cuál es la diferencia, pero ha sido respondida antes. Pero ahora estoy preguntando por qué hicieron estas diferencias? (Estoy hablando de Java aquí, no sé si lo mismo se aplica a otros idiomas)¿Por qué crear clases e interfaces abstractas?

Las dos cosas parecen muy similares. Las clases abstractas pueden definir un cuerpo de método, mientras que las interfaces no pueden, pero pueden heredarse múltiples interfaces. Entonces, ¿por qué ellos (por "ellos" me refiero a Sun cuando escribieron Java) hacen una cosa donde se puede escribir un cuerpo de método y este tipo puede ser heredado más de una vez por una clase.

¿Hay alguna ventaja en no poder escribir un cuerpo de método, o ampliar varias veces que no estoy viendo?

Respuesta

10

Dado que permitir que las clases hereden múltiples implementaciones para la misma firma de método conduce a la pregunta obvia, cuál debe usarse en tiempo de ejecución.

Java evita esto al admitir herencia múltiple solo para interfaces. Las firmas declaradas en cada interfaz se pueden combinar mucho más fácilmente (Java básicamente usa la unión de todos los métodos)

+0

¡Ah, sabía que debía haber algo que me faltaba, esto tiene sentido! – Paul

3

La herencia múltiple es más difícil de implementar en un lenguaje (realmente el compilador) ya que puede dar lugar a ciertos problemas. Estos problemas se han discutido aquí anteriormente: What is the exact problem with multiple inheritance.

Siempre he supuesto que esto fue un compromiso en Java. Las interfaces permiten que una clase cumpla múltiples contratos sin el dolor de cabeza de la herencia múltiple.

0

El otro enfoque que está describiendo es el enfoque utilizado por C++ (mixins, por ejemplo). Los problemas relacionados con dicha "herencia múltiple" son bastante complejos y tienen varias críticas en C++.

+0

C++ no tiene mixins como yo los entiendo. Mixins se puede agregar a una clase en tiempo de ejecución ("agregar comportamiento de Logger a esta instancia DBI"), que no es una parte central del lenguaje C++. –

+0

@Philip No sé a qué te refieres. Mixins se utilizan con bastante frecuencia en C++, quizás el más conocido en los libros de Grady Booch. –

+0

Creo que simplemente no estamos de acuerdo con la definición de "mixin". No es gran cosa, muévete. –

5

La herencia múltiple en C++ conduce a ambigüedades semánticas como diamond inheritance problem. MI es bastante poderoso, pero tiene consecuencias complejas.

Hacer que las interfaces sean un caso especial también aumenta la visibilidad del concepto como un medio de ocultar información y reducir la complejidad del programa. En C++, definir bases abstractas puras es un signo de un programador maduro. En Java, los encuentras en una etapa mucho más temprana en la evolución de un programador.

1

Hacerlos una cosa es la ruta que los chicos de Scala tomaron con Traits, que es una interfaz que puede tener métodos y admite herencia múltiple.

Creo que las interfaces, para mí, son claras, ya que solo especifican requisitos (diseño por contrato) mientras que las clases abstractas definen un comportamiento común (implementación), ¿entonces una herramienta diferente para un trabajo diferente? Las interfaces probablemente también permiten una generación de código más eficiente durante el tiempo de compilación.

0

herencia significa que hereda la naturaleza (sentido) y responsabilidad (comportamiento) de la clase padre, mientras que la implementación de interfaces significa que cumplir un contrato (por ejemplo Serializable), que puede no tener nada que ver con la naturaleza del núcleo o responsabilidad de la clase.

La clase abstracta le permite definir una naturaleza que desea que sea genérica y no directamente instanciable, porque debe ser especializada. Sabe cómo realizar algunas tareas de alto nivel (por ejemplo, tomar una decisión de acuerdo con algunos parámetros), pero no conoce los detalles de algunas acciones de nivel inferior (por ejemplo, calcular algunos parámetros intermedios), ya que depende de las opciones de implementación.Una alternativa para resolver este problema es el Strategy design pattern. Es más flexible, lo que permite la conmutación de estrategia en tiempo de ejecución y el comportamiento nulo, pero es más complejo (y la sincronización en tiempo de ejecución no siempre es necesaria). Además, puede perder algo de , que significa & tipping facilities (polimorfismo & la comprobación de tipos se vuelve un poco más difícil porque la Estrategia es un componente, no el objeto en sí).

clase abstracta = is-a, Estrategia =-tiene una edición

: como para la herencia múltiple, véase la respuesta del Ponto Gagge.

2

Considere este ejemplo:

public abstract class Engine 
{ 
    public abstract void switchPowerOn(); 
    public abstract void sprinkleSomeFuel(); 
    public abstract void ignite(); 

    public final void start() 
    { 
    switchPowerOn(); 
    sprinkleSomeFuel(); 
    ignite(); 
    } 
} 

clase abstracta puede ayudarle con tener métodos base sólida que puede o no puede ser anulado, pero en estos métodos se utiliza methos abstractos para proporcionar una oportunidad para hacer su cosa específica que . En mi ejemplo, diferentes motores tienen diferentes implementaciones de cómo encienden la alimentación, rociando algo de combustible para el encendido y haciendo el encendido, sin embargo, la secuencia de puesta en marcha del motor permanece siempre igual.

Ese patrón se llama "Método de plantilla de formulario" y es francamente el único uso sensato de las clases abstractas en Java para mí.

Cuestiones relacionadas