Search code examples
javagenericssignature

Error using generic return type (incompatible types: cannot be converted to T)


public class Main{
    private MyQueue queue = null;
    private MyStack stack = null;
    private MyList list = null;

    public static void main(String args[]){
        Main m = new Main();
        m.run();
    }
    
    public void run(){
        // only one data structure is not null.
        // for example, let's suppose that it's queue
        this.queue = new MyQueue();
        
        int intToAdd = 6;   // I want to add this number
        this.selectStruct().insert(intToAdd);       // I want to invoke the "insert" method of the current data structure in use
    }
    
    private <T> T selectStruct(){       // this should check with data structure is in use (so which of them is not null) and then return the reference
        if (this.queue!=null){
            return this.queue;
        }
        if (this.stack!=null){
            return this.stack;
        }
        if (this.list!=null){
            return this.list;
        }
    }
}

I want to use this method called selectStruct to select the current data structure in use and return the reference. And from this reference then call insert that invokes the correct insert method of the correct class.

The problem is that I have several errors. I have never used generics, so I'm a bit confused.

$ javac Main.java
Main.java:22: error: incompatible types: MyQueue cannot be converted to T
                        return this.queue;
                                   ^
  where T is a type-variable:
    T extends Object declared in method <T>selectStruct()
Main.java:25: error: incompatible types: MyStack cannot be converted to T
                        return this.stack;
                                   ^
  where T is a type-variable:
    T extends Object declared in method <T>selectStruct()
Main.java:28: error: incompatible types: MyList cannot be converted to T
                        return this.list;
                                   ^
  where T is a type-variable:
    T extends Object declared in method <T>selectStruct()
Main.java:17: error: cannot find symbol
                this.selectStruct().insert(intToAdd);
                                   ^
  symbol:   method insert(int)
  location: class Object
4 errors

Solution

  • Let MyQueue, MyStack, and MyList implement the same interface containing the methods you want all your data structures to implement, e.g:

    public interface IDataStructure {
        void insert(int intToAdd);
    }
    

    Your classes should then look like this:

    public class MyQueue implements IDataStructure{
    
        @Override
        public void insert(int intToAdd) {
            // TODO 
        }
    
    }
    
    public class MyStack implements IDataStructure{
    
        @Override
        public void insert(int intToAdd) {
            // TODO 
        }
    
    }
    
    public class MyList implements IDataStructure{
    
        @Override
        public void insert(int intToAdd) {
            // TODO 
        }
    
    }
    

    Finally, you can modify your selectStruct() method to return an IDataStructure:

    private IDataStructure selectStruct() {
        if (this.queue != null) {
            return this.queue;
        }
        if (this.stack != null) {
            return this.stack;
        }
        if (this.list != null) {
            return this.list;
        }
        return null;
    }