Pregunta Interfaz vs clase abstracta (OO general)


Recientemente tuve dos entrevistas telefónicas en las que me preguntaron acerca de las diferencias entre una interfaz y una clase abstracta. Les expliqué todos los aspectos de los que pude pensar, pero parece que están esperando que mencione algo específico, y no sé qué es.

Desde mi experiencia, creo que lo siguiente es verdad. Si me falta un punto importante, házmelo saber.

Interfaz:

Todos y cada uno de los métodos declarados en una interfaz deberán implementarse en la subclase. Solo eventos, delegados, propiedades (C #) y métodos pueden existir en una interfaz. Una clase puede implementar múltiples interfaces.

Clase abstracta:

Solo los métodos abstractos tienen que ser implementados por la subclase. Una clase abstracta puede tener métodos normales con implementaciones. La clase abstracta también puede tener variables de clase junto a Eventos, Delegados, Propiedades y Métodos. Una clase solo puede implementar una clase abstracta solo debido a la inexistencia de Multi-herencia en C #.

  1. Después de todo eso, al entrevistador se le ocurrió la pregunta "¿Y si tuviera una clase de Resumen con solo métodos abstractos? ¿Cómo sería eso diferente de una interfaz?" No sabía la respuesta, pero creo que es la herencia como se mencionó anteriormente ¿no?

  2. Otro entrevistador me preguntó qué pasaría si tuviera una variable pública dentro de la interfaz, ¿cómo sería eso diferente de la clase abstracta? Insistí que no puedes tener una variable pública dentro de una interfaz. No sabía lo que quería oír, pero tampoco estaba satisfecho.

Ver también:


1197
2018-04-17 16:42


origen


Respuestas:


Si bien su pregunta indica que es para "OO general", realmente parece centrarse en el uso de .NET de estos términos.

En .NET (similar para Java):

  • las interfaces no pueden tener estado o implementación
  • una clase que implementa una interfaz debe proporcionar una implementación de todos los métodos de esa interfaz
  • las clases abstractas pueden contener estados (miembros de datos) y / o implementación (métodos)
  • las clases abstractas se pueden heredar sin implementar los métodos abstractos (aunque dicha clase derivada es abstracta en sí misma)
  • las interfaces pueden ser hereditarias múltiples, las clases abstractas pueden no (esta es probablemente la razón más importante para que las interfaces existan por separado de las clases abstractas; permiten una implementación de herencia múltiple que elimina muchos de los problemas de MI general).

Como términos generales de OO, las diferencias no están necesariamente bien definidas. Por ejemplo, hay programadores de C ++ que pueden tener definiciones rígidas similares (las interfaces son un subconjunto estricto de clases abstractas que no pueden contener la implementación), mientras que algunos pueden decir que una clase abstracta con algunas implementaciones predeterminadas sigue siendo una interfaz o no abstracta. la clase todavía puede definir una interfaz.

De hecho, existe un modismo de C ++ llamado Interfaz no virtual (NVI) en el que los métodos públicos son métodos no virtuales que 'suenan' a los métodos virtuales privados:


632
2018-04-17 17:18



Qué tal una analogía: cuando estaba en la Fuerza Aérea, fui a entrenamiento de pilotos y me convertí en piloto de la USAF (Fuerza Aérea de los EE. UU.). En ese momento no estaba calificado para volar nada, y tuve que asistir al entrenamiento de tipo de aeronave. Una vez que califiqué, era piloto (clase de resumen) y piloto de C-141 (clase concreta). En una de mis tareas, se me asignó un deber adicional: Oficial de Seguridad. Ahora todavía era piloto y piloto de C-141, pero también desempeñaba funciones de Oficial de Seguridad (implementé ISafetyOfficer, por así decirlo). No se requirió que un piloto fuera un oficial de seguridad, otras personas podrían haberlo hecho también.

Todos los pilotos de la USAF tienen que seguir ciertas regulaciones de la Fuerza Aérea, y todos los pilotos C-141 (o F-16, o T-38) 'son' pilotos de la USAF. Cualquiera puede ser un oficial de seguridad. Entonces, para resumir:

  • Piloto: clase abstracta
  • C-141 Piloto: clase concreta
  • Oficial de ISafety: interfaz

Nota agregada: se suponía que era una analogía para ayudar a explicar el concepto, no una recomendación de codificación. Vea los diversos comentarios a continuación, la discusión es interesante.


754
2017-08-30 04:40



Creo que la respuesta que están buscando es la diferencia filosófica fundamental o OPPS.

La herencia de la clase abstracta se usa cuando la clase derivada comparte las propiedades principales y el comportamiento de la clase abstracta. El tipo de comportamiento que realmente define la clase.

Por otro lado, la herencia de interfaz se usa cuando las clases comparten un comportamiento periférico, que no define necesariamente la clase derivada.

Por ej. Un automóvil y un camión comparten muchas propiedades centrales y el comportamiento de una clase abstracta de Automóvil, pero también comparten algún comportamiento periférico como Generar escape que incluso las clases no automotrices como Drillers o PowerGenerators comparten y no necesariamente define un automóvil o un camión. , por lo que Car, Truck, Driller y PowerGenerator pueden compartir la misma interfaz IExhaust.


194
2017-08-31 12:09



Corto: las clases abstractas se usan para Modelado una jerarquía de clase de clases similares (por ejemplo, Animal puede ser una clase abstracta y Human, Lion, Tiger pueden ser clases derivadas concretas)

Y

La interfaz se usa para Comunicación entre 2 clases similares / no similares a las que no les importa el tipo de interfaz que implementa la clase (por ejemplo, Altura puede ser propiedad de la interfaz y puede ser implementada por Humano, Edificio, Árbol. No importa si puedes comer, puedes nadar puede morir o lo que sea ... solo importa algo que necesites para tener Altura (implementación en tu clase)).


163
2018-04-05 09:53



Hay un par de otras diferencias:

Las interfaces no pueden tener implementaciones concretas. Las clases base abstractas pueden. Esto le permite proporcionar implementaciones concretas allí. Esto puede permitir que una clase base abstracta proporcione realmente un contrato más riguroso, mientras que una interfaz realmente solo describe cómo se usa una clase. (La clase base abstracta puede tener miembros no virtuales que definen el comportamiento, lo que otorga más control al autor de la clase base).

Se puede implementar más de una interfaz en una clase. Una clase solo puede derivar de una sola clase base abstracta. Esto permite una jerarquía polimórfica usando interfaces, pero no clases base abstractas. Esto también permite una pseudo-multi-herencia usando interfaces.

Las clases base abstractas se pueden modificar en v2 + sin romper la API. Los cambios a las interfaces están rompiendo cambios.

[C # / .NET Specific] Las interfaces, a diferencia de las clases base abstractas, se pueden aplicar a tipos de valores (estructuras). Las estructuras no pueden heredar de clases base abstractas. Esto permite que los contratos de comportamiento / pautas de uso se apliquen a los tipos de valores.


74
2018-04-17 16:46



Herencia
Considera un auto y un autobús. Son dos vehículos diferentes. Pero aún así, comparten algunas propiedades comunes como dirección, frenos, engranajes, motor, etc.
Entonces, con el concepto de herencia, esto puede representarse como sigue ...

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

Ahora una bicicleta ...

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

Y un auto ...

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

Eso es todo Herencia. Los usamos para clasificar objetos en formas básicas más simples y sus hijos como vimos arriba.

Clases abstractas

Las clases abstractas son incompleto objetos. Para entenderlo más, consideremos la analogía del vehículo una vez más.
Un vehículo puede ser conducido. ¿Derecha? Pero diferentes vehículos se conducen de diferentes maneras ... Por ejemplo, no puede conducir un automóvil tal como conduce una bicicleta.
Entonces, ¿cómo representar la función de conducción de un vehículo? Es más difícil verificar qué tipo de vehículo es y conducirlo con su propia función; Tendría que cambiar la clase de controlador una y otra vez al agregar un nuevo tipo de vehículo.
Aquí viene el papel de las clases y métodos abstractos. Puede definir el método de unidad como abstracto para indicar que cada hijo heredado debe implementar esta función.
Entonces, si modificas la clase de vehículo ...

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

La bicicleta y el automóvil también deben especificar cómo conducirlo. De lo contrario, el código no se compilará y se generará un error.
En resumen ... una clase abstracta es una clase parcialmente incompleta con algunas funciones incompletas, que los niños que heredan deben especificar la suya propia.

Interfaces Las interfaces son totalmente incompletas. Ellos no tienen ninguna propiedad. Simplemente indican que los niños herederos son capaces de hacer algo ...
Supongamos que tiene diferentes tipos de teléfonos móviles con usted. Cada uno de ellos tiene diferentes formas de hacer diferentes funciones; Ej .: llama a una persona. El creador del teléfono especifica cómo hacerlo. Aquí los teléfonos móviles pueden marcar un número, es decir, se puede marcar. Vamos a representar esto como una interfaz.

public interface Dialable {
    public void dial(Number n);
}

Aquí el creador de Dialable define cómo marcar un número. Solo necesita darle un número para marcar.

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Al utilizar interfaces en lugar de clases abstractas, el escritor de la función que utiliza un Dialable no necesita preocuparse por sus propiedades. Ejemplo: ¿Tiene una pantalla táctil o teclado de marcado? ¿Es un teléfono fijo o un teléfono móvil? Solo necesita saber si se puede marcar; hereda (o implementa) la interfaz Dialable.

Y más importante, si algún día cambias el Dialable por uno diferente

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Puede estar seguro de que el código todavía funciona perfectamente porque la función que utiliza el marcador no depende (y no puede) de los detalles que no sean los especificados en la interfaz de Dialable. Ambos implementan una interfaz Dialable y eso es lo único que le importa a la función.

Los desarrolladores suelen utilizar interfaces para garantizar la interoperabilidad (uso intercambiable) entre objetos, siempre que compartan una función común (al igual que puede cambiar a una línea fija o teléfono móvil, en la medida en que solo necesite marcar un número). En resumen, las interfaces son una versión mucho más simple de las clases abstractas, sin ninguna propiedad.
Además, tenga en cuenta que puede implementar (heredar) tantas interfaces como desee, pero solo puede extender (heredar) una única clase principal.

Más información Clases abstractas vs Interfaces 


63
2018-06-14 13:11



Si considera java como lenguaje OOP para responder a esta pregunta, la versión Java 8 hace que parte del contenido de las respuestas anteriores quede obsoleto. Ahora la interfaz de Java puede tener métodos predeterminados con implementación concreta.

Oráculo sitio web proporciona diferencias clave entre interface y abstract clase.

Considera usar clases abstractas Si :

  1. Desea compartir el código entre varias clases estrechamente relacionadas.
  2. Espera que las clases que amplían su clase abstracta tengan muchos métodos o campos comunes, o que requieran modificadores de acceso que no sean públicos (como protegidos y privados).
  3. Desea declarar campos no estáticos o no finales.

Considere usar interfaces Si :

  1. Esperas que las clases no relacionadas implementen tu interfaz. Por ejemplo, muchos objetos no relacionados pueden implementar Serializable interfaz.
  2. Desea especificar el comportamiento de un tipo de datos particular, pero no le preocupa quién implementa su comportamiento.
  3. Desea aprovechar la herencia múltiple de tipo.

En términos simples, me gustaría usar

interfaz: Para implementar un contrato por múltiples objetos no relacionados

clase abstracta: Para implementar el mismo o diferente comportamiento entre múltiples objetos relacionados

Eche un vistazo al ejemplo del código para comprender las cosas de manera clara: ¿Cómo debería haber explicado la diferencia entre una interfaz y una clase abstracta?


33
2017-11-27 19:20



Los entrevistadores están ladrando un árbol extraño. Para lenguajes como C # y Java, existe una diferencia, pero en otros lenguajes como C ++ no existe. La teoría de OO no diferencia los dos, simplemente la sintaxis del lenguaje.

Una clase abstracta es una clase con implementación e interfaz (métodos virtuales puros) que se heredará. Las interfaces generalmente no tienen ninguna implementación sino solo funciones virtuales puras.

En C # o Java, una clase abstracta sin implementación difiere de una interfaz solo en la sintaxis utilizada para heredar de ella y el hecho de que solo se puede heredar de una.


30
2018-04-17 16:48



Al implementar las interfaces, usted está logrando la composición (relaciones "has-a") en lugar de herencia (relaciones "is-a"). Ese es un principio importante para recordar cuando se trata de cosas como patrones de diseño en los que necesitas usar interfaces para lograr una composición de comportamientos en lugar de una herencia.


29
2018-04-17 16:52



Explicaré Detalles de profundidad de la interfaz y la clase Resumen. Si conoce información general sobre la interfaz y la clase abstracta, entonces la primera pregunta llegará en su mente cuando deberíamos usar la Interfaz y cuando deberíamos usar la clase Resumen. Por lo tanto, verifique la explicación a continuación de Interfaz y clase abstracta.

  1. ¿Cuándo deberíamos usar Interface?

    Si no sabe acerca de la implementación solo tenemos especificación de requisitos, entonces vamos con Interface 

  2. ¿Cuándo deberíamos usar Abstract Class?

    si conoce la implementación pero no completamente (parcialmente la implementación), entonces vamos con la clase Abstract. 

    Interfaz

    cada método por defecto público abstracto significa que la interfaz es 100% puramente abstracta.

    Abstracto

    puede tener el método concreto y el método abstracto, qué es el método concreto, que tienen implementación en la clase abstracta,    Una clase abstracta es una clase que se declara abstracta; puede incluir o no métodos abstractos.

    Interfaz

    No podemos declarar la interfaz como privada, protegida

    P. ¿Por qué no declaramos la interfaz como privada y protegida?

    Debido a que el método de la interfaz por defecto es el resumen público, tenemos que razonar que no estamos declarando la interfaz como privada y protegida.

    Método de interfaz
       tampoco podemos declarar la interfaz como privada, protegida, final, estática, sincronizada, nativa .....

    Daré la razón:  por qué no estamos declarando el método sincronizado porque no podemos crear el objeto de la interfaz y sincronizamos el trabajo en el objeto así que nuestra razón es que no estamos declarando el método sincronizado  El concepto transitorio tampoco es aplicable porque el trabajo transitorio con sincronizado.

    Abstracto 

    estamos felices de usarlo con estática final pública, privada .... significa que no se aplican restricciones en abstracto.

    Interfaz

    Las variables se declaran en la interfaz como una final estática pública predeterminada, por lo que tampoco se declara la variable como privada, protegida.

    El modificador volátil tampoco es aplicable en la interfaz porque la variable de la interfaz es por defecto la variable final y final estática pública no puede cambiar el valor una vez que asigna el valor a la variable y una vez que declara la variable en la interfaz debe asignar la variable.

    Y la variable volátil es mantener los cambios por lo que es opp. al final esa es la razón por la que no usamos variables volátiles en la interfaz.

    Abstracto

    Variable abstracta no es necesario declarar pública estática final.

Espero que este artículo sea útil.


23
2018-05-31 06:33



Para .Net,

Su respuesta a El segundo entrevistador también es la respuesta al primero ... Las clases abstractas pueden tener implementación, Y el estado, las interfaces no pueden ...

EDITAR: En otra nota, ni siquiera usaría la frase 'subclase' (o la frase 'herencia') para describir las clases que están 'definidas para implementar' una interfaz. Para mí, una interfaz es una definición de un contrato que una clase debe cumplir si se ha definido para 'implementar' esa interfaz. No hereda nada ... Tienes que agregar todo tú mismo, explícitamente.


21
2018-04-17 16:48