Search code examples
javagenericsinheritanceinterfacecommand-pattern

Combining different types of command interfaces using generics/inheritance


I'm using the command pattern to encapsulate logic in "command" objects. I currently have two types of command interfaces:

public interface ObjectCommand
{
    public void execute(Object object);
}

And one that makes the execute method return something:

public interface ObjectToArrayCommand
{
    public Object[] execute(Object object);
}

I was wondering if I could combine these two different interfaces into one interface, or have both share the same superclass interface using generics and/or inheritance, for example something like:

public interface Command<T,U>
{
    public U execute(T t);
}

The problem I have with this scheme is that I cannot make parameter "U" be "void/no object". Is there another way?

I know I can use subclasses to give parameters that are MORE specific, like "Object" can become "String" in a subclass and it would still compile. But again, "Object" cannot become "void".

The reason I want to combine these two into one interface is because it is easier (conceptually speaking) if EVERY command implements the same interface instead of having two (or more) types of commands that are being used together.


Solution

  • What you are looking is java.lang.Void , a placeholder for void keyword

    public interface ObjectCommand
    {
        public void execute(Object object);
    }
    
    
    public interface ObjectToArrayCommand
    {
        public Object[] execute(Object object);
    }
    

    can be combined as

    public interface Command<T, U> {
        public U execute(T t);
    }
    
    class CheckGenerics {
    
        public static void main(String[] args) {
    
            Command<Object, Class<Void>> command1 = new Command<Object, Class<Void>>() {
    
                @Override
                public Class<Void> execute(Object t) {
    
                    return Void.TYPE;
    
                }
            };
    
            Command<Object, Object[]> command2 = new Command<Object, Object[]>() {
    
                @Override
                public Object[] execute(Object t) {
    
                    return new Object[] { t };
                }
    
            };
    
            Class<Void> a = command1.execute(new Object());
            System.out.println(void.class == a); // prints true
    
            Object[] b = command2.execute(new Object());
            System.out.println(b);
    
        }
    

    Check the documentation of Void Class here ,the javadoc states that

    The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void..Note that Void class cannot be instantiated,which is precisely what we want