2012-02-10 10 views
7

Digamos que alguien le da una clase, Super, con los siguientes constructores:¿Cómo llamar a un constructor diferente condicionalmente en Java?

public class Super 
{ 
    public Super(); 
    public Super(int arg); 
    public Super(String arg); 
    public Super(int[] arg); 
} 

Y digamos que desea crear una subclase Derived. ¿Cómo se llama condicionalmente un constructor en Super?

En otras palabras, ¿cuál es la forma "correcta" de hacer algo como esto?

public class Derived extends Super 
{ 
    public Derived(int arg) 
    { 
     if (some_condition_1) 
      super(); 
     else if (some_condition_2) 
      super("Hi!"); 
     else if (some_condition_3) 
      super(new int[] { 5 }); 
     else 
      super(arg); 
    } 
} 
+0

cuáles son algunos ejemplos de 'some_external_condition'? Parece que cualquier condición debería ser verificada * después de que se llame a '' super'. – ggreiner

+0

@ggreiner: no tiene que ser externo, en realidad. Cambié ligeramente el ejemplo. Podría basarse simplemente en el argumento del usuario (que más bien podría ser una enumeración en lugar de un número entero, pero eso no está relacionado). – Mehrdad

Respuesta

4

Sí, lo que dijo @Johan Sjöberg.

También parece que su ejemplo es muy artificial. No hay una respuesta mágica que aclare este lío :)

Por lo general, si tienes tantos constructores, sería una buena idea refactorizarlos como cuatro clases separadas (una clase solo debería ser responsable de un tipo de cosa)

+0

Sí, no sé ... fue un problema con el que se encontró un amigo, no algo con lo que me encontré. Totalmente de acuerdo con el tercer párrafo también. +1 – Mehrdad

+3

Me he encontrado con este problema en código real: escribir código compatible hacia atrás para android: 'LinearLayout' tiene diferentes constructores según el valor de' android.os.Build.VERSION.SDK_INT'. – Timmmm

1

super debe ser la primera instrucción en un constructor, por lo tanto, la lógica de su muestra no es válido.

La forma correcta es crear el mismo 4 constructores en su clase extendida. Si necesita una lógica de validación, puede usar, por ejemplo, el patrón builder. También puede, como se sugiere en los comentarios de @davidfrancis, hacer todas las construcciones privadas y proporcionar un método de fábrica estático. Por ejemplo,

public static Derived newInstance(int arg) { 
     if (some condition) { 
     return new Derived(arg); 
     } 
     // etc 
} 
+0

¿Cómo se verifican las condiciones? – Mehrdad

+1

@Merhdad, dejas eso hasta la clase que construye el objeto. Esto puede ser, por ejemplo, un 'generador' si desea realizar comprobaciones específicas. –

+0

O tiene un método estático en una clase que toma una condición, lo inspecciona y luego instancia y devuelve una instancia de la clase. constructores "extra" en Derived podrían ser privados en este caso. Esto no es necesariamente un camino por recorrer, solo otra receta. –

0

No se puede hacer tal como super debe ser la primera instrucción en un constructor.

La alternativa adecuada es una clase de constructor y tener un constructor en la clase derivada para cada constructor en la superclase.

por ejemplo.

Derived d = new DerivedBuilder().setArg(1).createInstance(); 

public class DerivedBuilder { 

    private int arg; 

    // constructor, getters and setters for all needed parameters 

    public Derived createInstance() { 
     // use appropriate constructor based on parameters 
     // calling additional setters if need be 
    } 
} 
4

Use fábricas estáticas, y cuatro constructores privados.

class Foo { 
public static Foo makeFoo(arguments) { 
    if (whatever) { 
     return new Foo(args1); 
    } else if (something else) { 
     return new Foo(args2); 
    } 
    etc... 
    } 
    private Foo(constructor1) { 
    ... 
    } 
    ... 
} 
1

No se puede hacer eso, pero se puede hacer esto desde el código que llama a su clase:

 if (some_condition_1) 
      new Super(); 
     else if (some_condition_2) 
      new Super("Hi!"); 
     else if (some_condition_3) 
      new Super(new int[] { 5 }); 
     else 
      new Super(arg); 
Cuestiones relacionadas