2010-02-24 15 views
8

Pasé de Java 1.4 (empresa anterior) a Java 1.6 (nueva compañía). Lo que he observado es que en el caso de 1.4, la mayoría de los marcos de propiedad se definieron utilizando interfaces y patrones de plantillas, mientras que con 1.6 la mayoría de los marcos se definen en torno a los genéricos.Genéricos vs. Interfaces

Mientras sigo tratando de controlar Generics, mi pregunta es: ¿este es un enfoque de diseño correcto? Las interfaces hacen que su diseño sea más flexible/desacoplado. Mientras que los genéricos, implementan la seguridad de tipo y lo obligan a pasar alrededor de un tipo específico de clase. Realmente no ayuda a desacoplar su código. ¿Es esto correcto?

Un ejemplo -

public MyWizard extends SignupWizard<SignupSection, SignupObject, SignupListener, SignupView>{ 
} 

en lugar del diseño sería más flexible si era ..

public interface Wizardable{ 
    public SignableSection getSection(); 
    public SignableObject getSignableObject(); 
... 
} 

public MyWizard implements Wizardable{ 
.... 
} 
+1

Por favor, mejore su ejemplo. Por ejemplo, ¿cuál es la definición de SignupWizard? Dé algunos ejemplos concretos de marcos en los que se usan genéricos de la manera en que usted habla. La pregunta de "genéricos vs. interfaces" no tiene mucho sentido para mí, porque a menudo ambos se usan juntos. "Anotaciones vs. interfaces" tiene más sentido. –

+0

Parece el tipo de cosas que esperaría en C++, no en Java. –

Respuesta

4

No diría que nada era genéricos vs interfaces, cada uno tiene sus diferentes necesidades y usos. El uso de parámetros genéricos en la forma mencionada en la publicación original sirve para múltiples propósitos. Permite a los desarrolladores definir las clases base que componen los tipos de objetos de campo de la clase. Al usar esto, el desarrollador puede aceptar objetos de clase como parámetros sobre los que pueden usar la reflexión para crear los objetos reales y establecer los campos, o simplemente aceptar el objeto completo para establecer en primer lugar.El problema relacionado con la necesidad de objetos de clase en lugar de new T() o similar se conoce como type erasure.

Otra ventaja del uso de genéricos es que no necesita encasillar todo el tiempo cuando usa campos o métodos de una superclase; usted conoce personalmente sus tipos, pero Java no tiene ese tipo de información almacenada en ninguna parte. Un beneficio adicional es que todos sus métodos getter/setter pueden usar los parámetros genéricos y exponer un frente más sensible a otros objetos que dependen del hecho de que configure campos especializados en el objeto mencionado anteriormente.

El problema con el uso de interfaces para hacer lo mismo que genéricos es que necesita métodos adicionales para acceder a los tipos especializados y convertirlos, antes de devolverlos (o verificar tipos entrantes y luego establecer campos para los objetos). Está haciendo el diseño más complejo, y realmente no ayuda con el desacoplamiento en absoluto.

Como mencioné en un comentario, cualquier subclase establecerá esos parámetros de tipo y no expondrá nada al usuario. Entonces puede tener algo como class MegaSignupWizard extends SignupWizard<MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView> y todo sigue siendo perfectamente válido con MegaSignupWizard teniendo acceso a métodos especializados en las clases sin necesidad de emitir. Ahora eso es genial :)

1

me he dado cuenta de que muchos de los nuevos marcos tienden a utilizar las anotaciones en lugar de interfaces , pero no los he notado usando genéricos en lugar de interfaces (lo que sea que signifique, por favor explique más).

Con la ayuda de genéricos, es posible reducir la duplicación de código y mejorar la seguridad de tipo, cuando tiene una interfaz con parámetros de tipo genérico y la misma interfaz funcionará para muchos tipos diferentes. Las colecciones en el paquete java.util son un buen ejemplo de cuándo los genéricos son útiles.

En el caso de las anotaciones, a veces siento que se usan en exceso y una interfaz sería mejor; por ejemplo, con una interfaz es fácil saber qué parámetros debe tomar un método, pero en otros casos una anotación es más flexible y poderosa .

+0

Anotaciones en lugar de interfaces? ¿Qué sería tal marco? –

+1

Por ejemplo, la anotación @GET en la API de Servlet 3.0: http://today.java.net/article/2008/10/08/introduction-servlet-30 –

+0

@Murali: ¿Has oído hablar alguna vez de JPA? Casi solo anotaciones. – whiskeysierra

3

Generics le permite implementar métodos en el tipo general mientras que las interfaces solo definen las firmas. Tal vez se abuse de él a veces para actuar como el trait de Scala, pero en su mayoría tienen dos propósitos diferentes. Si todo fuera una interfaz, habrá una gran cantidad de código duplicado o delegaciones en alguna clase de ayuda.

0

Eche un vistazo a Jung2 para ver dónde los genéricos se vuelven realmente poderosos. Básicamente, cualquier objeto puede ser un vértice o un borde que crea algunas ideas realmente interesantes en los algoritmos de red. No podrías hacer esto solo con interfaces.

No estoy seguro de que su uso anterior también se vea bien. Si se extiende desde un objeto o implementa una interfaz, realmente no desea pasar objetos así. Los genéricos se usan para implementar una clase con tipo abstracto, como una colección, que podría actuar sobre cualquier cosa. ¿Qué sucede si paso SignupWizard<int, int, int, int> que es perfectamente válido?

Para esa idea en particular, quizás quiera usar interfaces. Tener una interfaz que defina wizardaction, cada objeto que lo implemente y mywizard pueda .addaction (int position, wizardaction action). De hecho, ese es definitivamente un problema de interfaces.

Estoy de acuerdo con los demás: los genéricos se han usado cuando las bibliotecas los necesitan.

+0

Si el vértice y el borde tienen una interfaz súper, entonces un objeto puede ser un vértice o un borde. –

+0

Pero no puede haber escrito parámetros en los bordes. Tienes que usar un objeto o pegarlo a un tipo. – whiskeysierra

+0

Es perfectamente válido. Cualquier subclase establecerá esos parámetros de tipo y no expondrá nada al usuario. Así que puedes tener algo como MegaSignupWizard que extiende SignupWizard y todo sigue siendo perfectamente válido con MegaSignupWizard teniendo acceso a métodos especializados en las clases sin necesidad de emitir. –

1

Creo que es genéricos e interfaces, ya que cualquier interfaz puede hacer uso de los genéricos en sí. El problema que veo cuando comienzas a usar clases genéricas (abstractas), pierdes la flexibilidad de usar la composición. Si bien no hay nada malo acerca de la herencia como tal, hay que diseñar para ello y existen muchas dificultades.

+0

Correcto, y uno de los puntos de Bloch en "Java efectivo" es favorecer la composición sobre la herencia. Mi teoría, siempre que veo un uso intensivo de las clases de genéricos y abstractos, es que los programadores simplemente no están tan familiarizados con las interfaces como lo están con los últimos juguetes en Java (Generics, Annotations). Entonces, cuando vemos todos los marcos como respuestas, no significa necesariamente que este sea el único camino verdadero por recorrer. Solo el tiempo probará si su diseño fue robusto y maleable, supongo, es decir, si existirá algo así como log4j. – michaelok

Cuestiones relacionadas