0

I have a class like this

class Dummy{
    public getData(Info info){
        List<SomeType> list = info.getDataAsPerInfo();

        List<SomeType> result=new List<>();  

        for(SomeType someType: list){
            // extracting data from someType, lets say this data is 
            // resType (it also of SomeType)
            result.add(resType);  
        }
    }

    public static void main(String args[]){
        Info1 info = new Info1();   // Info1 extends Info
        // adding paramters to info
        new Dummy().getData(info);
    }
}

Now the problem is that I have several Info classes like Info1, Info2 ... and there getData method might return different types of list. I can't figure how to achieve this without rewriting the code for each and every Info class( this would involve replacing SomeType with the return type of that class' getdataAsPerInfo function). Is there a way such that I can somehow use SomeType according to the Info type that is passed to the getData function? What would be the best approach in this case? Thanks !!

2
  • Do you want to return subclasses/implementers of SomeType based on Info type? Commented Aug 10, 2016 at 12:30
  • Thanks for the reply, using the list I do some more operations in getData(), I don't understand what exactly you mean !! Commented Aug 10, 2016 at 12:37

3 Answers 3

2

Just take a look at the Oracle tutorial for Generics.

You can't only define one specific class as the type for your lists elements but also families of classes or classes implementing a specific interface.

edit to incorporate comments.

When your Info.getDataAsPerInfo() returns Lists of different Objects depending on which InfoX class is used, this would be a use case for a generic interface.

public interface Info<T> {
    List<T> getDataAsPerInfo();
}

with implementations like:

public class Info1 implements Info<SomeType> 

or

public class Info2 implements Info<SomeOtherType>

Then your Dummy-class would look like

class Dummy {
    public getData(Info<T> info) {
        List<T> list = info.getDataAsPerInfo();

        List<T> result=new List<>();  

        for(T someType: list){
            // extracting data from someType, lets say this data is 
            // resType (it also of SomeType)
            result.add(resType);  
        }
    }

    public static void main(String args[]){
        Info1 info = new Info1();   // Info1 extends Info<SomeType>
        // adding paramters to info
        new Dummy().getData(info);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Hey Thanks for the reply, I did go through Generics tutorials but the idea I got after reading about it is that it asks us to mention the specific SubType like String etc so that we do not have to do casting while getting data from the list down the line. I also understood how it helps to resolve some issues at compile time rather than runtime. I dont understand how to utilize it in my case where I can't declare a specific SomeType such as String :(
Just for clarification: Your InfoX objects return Lists of different objects from their getDataAsPerInfo methods? Like Info1 returns a list of Strings, Info2 returns a list of Integers ans so on?
infoX objects returns a list of type SomeType where SomeType is a user-defined type, not primitive or String !!
1

I don't think you need to fiddle with generics here. You are looking for a solution where you could decide the functionality of SomeType in runtime (polymorphically). Have look at this solution.

    private interface SomeType {
        void doAThing();
    }

    private class AnotherType implements SomeType {

        @Override
        public void doAThing() {
            System.out.println("AnotherType.doAThing");
        }
    }

    private class OneMoreType implements SomeType {

        @Override
        public void doAThing() {
            System.out.println("OneMoreType.doAThing");
        }
    }

    private abstract class Info {
        public abstract SomeType getDataAsPerInfo();
    }

    private class Info1 extends Info {

        @Override
        public SomeType getDataAsPerInfo() {
            return new AnotherType();
        }
    }

    private class Info2 extends Info {

        @Override
        public SomeType getDataAsPerInfo() {
            return new OneMoreType();
        }
    }

Now you can return SomeType from Info and specifically implement the functionality in subclasses.

1 Comment

Hey thanks for the reply. I get the understanding of your idea. Can you please show how to finally use this idea inside the main class ?
1

If the info of each class is a different type but either extends or implements a main supertype you can use List< ? extends Type > which would work

You could always use List< ? > which returns any value as the generic, it's basically an unknown object so just have getData return List< ? > and it should work fine, then check they type with "instanceof" or other ways of doing it, this should work for what you're trying to achieve.

Or for the method you're using (it looks like) you can use T settings, here's a snippet of code with what I think you're trying to achieve.

    public <T> List<T> getInfo(T type) {
        // T here would be the type
        return new ArrayList<T>();
    }

Your question is kind of ambiguous so if you could explain more of what you're trying to do then I could help a lot more.

4 Comments

Don't encourage problematic code by putting the <?> right up front, OP mentioned Info.* classes extend Info. Put the extends part first... Probably mention PECS...
Ah okay, I see where you're coming from and I do agree that putting the extend bit would be loads better, I'll switch them now, and I have no idea what PECS is, so I wouldn't know how to explain it.
Ok, great. Also, I advise you to read up on PECS, or Producer Extends, Consumer Super - just an acronym to remember when dealung with generics. Helped me through fixing some quirky code...
Hey @C.Donavon thanks for the answer. I get some idea about what you are saying. But wouldn't using instanceOf ultimately force me to write the code multiple times, each time I will have to cast the values to that type. I however have added some more code so that you can get an idea what I have to do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.