2010-02-19 3 views
5

Estoy usando la biblioteca GWT. Hay una clase base llamada Widget de la que heredan todos los widgets. Algunos widgets implementan ciertas interfaces (por ejemplo, HasText), otros no. A veces deseo garantizar que algo que se transmite como argumento a una función es de cierta clase Y implementa una cierta interfaz.¿Puedo garantizar que estoy escribiendo en la clase Y la interfaz de un argumento?

Por ejemplo, deseo tener una función que adopte un argumento X, donde X es del tipo de clase Widget AND del tipo de interfaz HasText. Deseo tener este comportamiento porque solo se pueden agregar Widgets a los contenedores de diseño, y HasText especifica el conjunto completo de comportamientos que realmente necesito de dicho Widget.


En forma de pseudocódigo, podría ser:

public void fx(I_AM_A_Widget_AND_IMPLEMENT_INTERFACE_HasText x){ 
    //do stuff with x, which is guaranteed to be a Widget AND implement HasText 
} 

Es éste en todo lo posible en Java? Si hay varias formas de hacerlo, ¿hay una forma preferida/mejor?

+0

Situaciones como estas son las razones por las que odio el tipeo nominal. – dsimcha

Respuesta

0

Gracias por tanto de sus soluciones. Al final, decidí que la mejor solución era simplemente especificar tipos acotados en la parte superior de la definición de la clase. Por ejemplo, utilicé el formulario

public class Example<Editable extends Widget & HasText> { 
    private Editable editor = null; 

    //do stuff in various methods (including the constructor) with the 
    //editor variable and the Editable type. 
} 

Escogí esta solución por algunas razones.

  1. Las dos soluciones mencionadas anteriormente requieren el uso de métodos (repetitivo) que no se relacionan realmente con la funcionalidad empresarial, sino que están relacionadas con eludir las limitaciones del lenguaje.
  2. Anon, su solución es correcta, pero tengo el problema de no poder declarar una variable que mantendría una referencia al objeto genérico que devuelve su método. Creo que este es el caso porque el objeto genérico devuelto por su método solo existe en el nivel del método y no en la clase. Tal vez me he perdido alguna sintaxis que me permita declarar variables que tienen propiedades genéricas.
  3. Yishai, su solución también funciona, pero luego tengo el problema de tener que declarar un método separado en cada interfaz que deseo garantizar el soporte, esto parecía engorroso.
  4. Estos tipos delimitados declarados en el "encabezado" de clase solo necesitan declararse una vez. Parece la declaración más escueta de tipos acotados genéricos disponibles en Java.
  5. Puede declarar más de un tipo delimitado en el "encabezado" de la clase.
  6. Si utiliza este método exclusivamente, todos los posibles tipos acotados se declaran en la misma ubicación en su código.

La declaración de tipos acotados en el encabezado de clase es la mejor solución que he encontrado. Todavía estaría interesado en saber si es una manera de declarar permanentemente (para que se pueda acceder a través de diferentes clases) un tipo delimitado, en lugar de declararlos por clase.

7

Usted puede ser capaz de utilizar un método genérico aquí:

public <T extends Widget & HasText> void fx(T x) 

El compilador inferirá el tipo de T de forma automática, por lo que no sintaxis adicional al llamar al método.

1

La forma en que manejaría esto es agregar un método a la interfaz HasText para devolver el Widget, y la implementación simplemente lo devolverá.

public class MyClass extends Widget implements HasText { 

      @Override 
      public Widget getMyWidget() { 
       return this; 
      } 
    } 

Así que si un método necesita un widget, que acaba de llamar el método de HasText getMyWidget(). Sí crea algunos repetitivos, pero ayuda con la comprobación de tipo estática.

Si no te importa tanto la comprobación del tipo estático, simplemente podrías tener un contrato (afirmación en el JavaDoc) de que la interfaz HasText solo está destinada a implementarse en Widgets, y luego simplemente lanzar cada vez que necesites el widget.

A continuación, el método sólo se parece a

public void fx(HasText text) //... 
Cuestiones relacionadas