HYBR1D
HYBR1D

Reputation: 462

Java - How do I pass the return type of a method as parameter?

I'm trying to make a small game with a TUI. The TUI should have a get() method that should take a String question and a return type as parameter, so you can use it to request an object.

For example, get("What is your name?", String) should return a String and get("What color do you want?", Color) should return a Color.

This is what I've come up with:

public interface View {

    public <T> T get(String question, Class<T> type) throws InputException;

}

public class TUI implements View {

    public Color get(String question, Class<Color> type) {
        // code
    }

    public String get(String question, Class<String> type) {
        // code
    }

}

Color color = Game.getView().get("What piece do you want to place?", Color.class);

Unfortunately, the methods in TUI are not accepted as implementations of public <T> T get(String question, Class<T> type) throws InputException;. Is there any way I can do this?

Upvotes: 4

Views: 1022

Answers (4)

Pado
Pado

Reputation: 1637

You can use something similar to Template Method Design Pattern.

public interface TypeTemplate {
    public Object get(String question);
}
public class ColorTemplate implements TypeTemplate {
    @Override public Color get(String question) { /*code for color*/ }
}
public class StringTemplate implements TypeTemplate {
    @Override public String get() { /*code for string*/ }
}

public class TUI {
    public Color get(String question, ColorTemplate templ) {
        return templ.get(String question)
    }
    public String get(String question, StringTemplate templ) {
        return templ.get(String question);
    }
}



public static void main(String args[]) {
    TUI tui = new TUI();
    String string = tui.get("What is your name?", new StringTemplate());
    Color color = tui.get("What color do you want?", new ColorTemplate());
}

You can of course replace Object type in TypeTemplate with something less generic. You can also make TypeTemplate one abstract class; this way if all (or some) of your get() methods will have to share some code you can add methods in this class and call from the subclasses. e.g.

public abstract class TypeTemplate {
    public abstract Object get(String question);
    protected void init() {/*some initialization code*/} 
    protected void cleanup(){/*some more code*/}
}
public class ColorTemplate implements TypeTemplate {
    @Override
    public Color get(String question) {
        init();
        /*code for color*/
        cleanup(); 
    }
}
public class StringTemplate implements TypeTemplate {
    @Override
    public String get() {
        init();
        /*code for string*/
        cleanup(); 
    }
}

Upvotes: 0

David
David

Reputation: 3937

Your TUI class is not valid because under type erasure both get methods have the same arguments.

You might want to do this:

public interface View<T> {
    T get(String question, Class<T> type) throws InputException;
}

public class ColorTUI implements View<Color> {
    public Color get(String question, Class<Color> type) {
        // code
    }
}

public class StringTUI implements View<String> {
    public String get(String question, Class<String> type) {
        // code
    }
}

Upvotes: 0

VanBaffo
VanBaffo

Reputation: 259

Try to make two classes AskColor and AskString that implements View, with method respectively

  public Color get(String question, Class<Color> type) {
    // code
}

public String get(String question, Class<String> type) {
    // code
}

and the interface View with method

public T get(String question, Class<T> type) throws InputException;

Upvotes: 0

Alan Blyth
Alan Blyth

Reputation: 195

Keeping it type safe by splitting the functions would seem more appropriate:

Color color = Game.getView().getColor("What piece do you want to place?");
String string = Game.getView().getString("What piece do you want to place?");

Upvotes: 6

Related Questions