Estilo de código Java: interfaces frente a clases abstractas

Si no necesita una clase abstracta con ciertos detalles comunes a todas las implementaciones, entonces no hay necesidad real de una clase abstracta. La complejidad a menudo se agrega a las aplicaciones porque se percibe cierta necesidad de admitir características futuras que aún no se han definido. Quédese con lo que funciona y refactorice más tarde.

Respuesta 1

No, ella es inexperta, no está bien. Se prefiere usar interfaces, y escribir superclases abstractas redundantes por redundancia es redundante.

UsesFoo debe preocuparse por el comportamiento especificado por la interfaz, no por la superclase de sus dependencias.

Respuesta: 2

Para mí "ella no estaba acostumbrada" no es razón suficiente. Pídele que explique sobre eso.

Personalmente usaría su solución, porque:

  1. AbstractFoo es redundante y no tiene ningún valor en la situación actual.

  2. Incluso si se necesitaba AbstractFoo (para alguna funcionalidad adicional), siempre usaría el tipo más bajo necesario: si GeneralFoo era suficiente, entonces usaría eso, no alguna clase derivada de él.

Respuesta: 3

Depende solo de tu problema.

Si usa solo interfaces, entonces si todas sus clases tienen un mismo método, tendría que implementarse de forma redundante (o alejarse a una clase Util).

Por otro lado, si escribe una clase abstracta intermedia, resolvió ese problema, pero ahora su subclase puede no ser una subclase de otra clase, debido a la ausencia de herencia múltiple en Java. Si ya era necesario extender alguna clase, esto no es posible.

Entonces, en breve, es una compensación. Use lo que sea mejor en su caso particular.

Respuesta: 4

No hay daño en usar directamente una interfaz en código. Si lo hubiera, Java no tendría interfaces.

Las desventajas de usar una interfaz directamente incluyen no poder acceder y métodos específicos de clase que no están implementados en la interfaz. Para interfaces mal escritas, o clases que agregan una gran cantidad de "otras" funcionalidades, esto no es deseable ya que pierde la capacidad de acceder a los métodos necesarios. Sin embargo, en algunos casos esto podría ser un reflejo de una mala elección de diseño al crear la interfaz. Sin detalles es muy difícil saberlo.

Las desventajas de usar la clase base directamente incluyen ignorar eventualmente la interfaz, ya que no se usa con frecuencia. En casos extremos, la interfaz se convierte en el código equivalente de un apéndice humano; "presente pero proporcionando poca o ninguna funcionalidad". No es probable que las interfaces no utilizadas se actualicen, ya que todos usarán la clase abstracta base directamente de todos modos. Esto permite que su diseño se pudra silenciosamente desde el punto de vista de cualquiera que realmente intente usar la interfaz. En casos extremos, no es posible manejar una clase extendida a través de la interfaz para realizar alguna funcionalidad crítica.

Personalmente, estoy a favor de devolver las clases a través de su interfaz y almacenarlas internamente en los miembros a través de su subclase más baja. Esto proporciona un conocimiento íntimo de la clase dentro de la encapsulación de la clase, obliga a las personas a usar la interfaz (manteniéndola actualizada) externamente, y la encapsulación de la clase permite un posible reemplazo futuro sin demasiado alboroto.

Respuesta: 5

Tengo curiosidad por saber si hay una ventaja para el segundo estilo, o una desventaja para el primer estilo, que me falta

Eso explica el primer interfacesestilo:

  1. A menudo, el diseño es tal que la interfaz es la interfaz pública del concepto, mientras que la clase abstracta es un detalle de implementación del concepto.

    Por ejemplo, considere Listy AbstractListen el marco de la colección. Listes realmente lo que los clientes suelen buscar; cada vez menos personas conocen AbstractListporque es un detalle de implementación para ayudar a los proveedores (implementadores) de la interfaz), no a los clientes (usuarios) de la clase.

  2. La interfaz es un acoplamiento más flexible, por lo tanto, más flexible para soportar cambios futuros.

  3. Utilice el que más claro representa el requisito de la clase, que a menudo es la interfaz.

    Por ejemplo, a Listmenudo se usa en lugar de AbsrtactListo ArrayList. Al usar la interfaz, puede ser más claro para un futuro mantenedor que esta clase necesita algún tipo de List, pero no necesita específicamente unAbstractList o un ArrayList. Si esta clase se basa en alguna AbstractListpropiedad específica, es decir, necesita usar un AbstractListmétodo, entonces usar en AbstractList list = ...lugar de List list = ...puede ser una pista de que este código se basa en algo específico de un AbstractList.

  4. Puede simplificar las pruebas / burlas para usar la interfaz más pequeña y abstracta en lugar de usar la clase abstracta.

Respuesta: 6

Algunos consideran que es una mala práctica declarar variables por sus AbstractFoofirmas, ya que la UsesFooclase se combina con algunos de los detalles de implementación de foo.

Esto conduce a una menor flexibilidad: no puede intercambiar el tipo de tiempo de ejecución de foo ninguna clase que implemente la GeneralFoointerfaz; solo puede inyectar instancias que implementen el AbstractFoodescendiente, dejándolo con un subconjunto más pequeño.

Idealmente, debería ser posible que las clases UsesFoosolo conozcan las interfaces de los colaboradores que usan y no los detalles de implementación.

Y, por supuesto, si no hay necesidad de declarar nada abstract en una abstract class AbstractFoo implements GeneralFoo, es decir, no hay una implementación común que todas las subclases reutilicen, entonces esto es simplemente un desperdicio de un archivo y niveles adicionales en su jerarquía.

Respuesta: 7

¿Cómo puedo hacer fácilmente lo siguiente en GWT? (El siguiente código es ilegal ya que String.format no se emula). Largo lTime = System.currentTimeMillis ()% (24 * 60 * 60 * 1000); larga l = hora / (60 * 60 * 1000); ...

Mientras ejecuta este código: privado void getData (DataSnapshot dataSnapshot) {for (DataSnapshot ds: dataSnapshot.getChildren ()) {Log.d (TAG, "UserID inside getData:" + userID); Log.d (...

Estoy usando Tiles 3 con Spring MVC 3.2. El siguiente es el código <tiles-definitions> <definition name = "base.definition" template = "/ pages / Layout / Layout.jsp"> <put-attribute name = "title" ...

Soy nuevo en JNA y al intentar mi primer programa para enumerar todos los procesos en Windows me he encontrado con algunos problemas. Por alguna razón, obtengo el siguiente resultado: [pid = 0, name = ???????? ] [pid = 4, ...