hawarden_
hawarden_

Reputation: 2160

Java : generic type with type parameters?

I have a class like this :

public class MyClass <T extends Model1, X extends Model2> {

    private CommonMessage<T,X> someMethod() {
        ....
    }
}

Now I have a customized message type MyMessage extends CommonMessage, so I want to know how to have generic type that still having T and X as parameters ? For example :

public class MyClass <M extends CommonMessage, T extends Model1, X extends Model2> {

    private M<T,X> someMethod() {
        ....
    }
}

Upvotes: 0

Views: 80

Answers (1)

Tashkhisi
Tashkhisi

Reputation: 2252

Short answer:

First of all as CommonMessage is generic, extending it in a non-generic way is very bad so you should have done M extends CommonMessage<T, X> And this way because type parameter passed to CommonMessage at class declaration you should not mention this parameter type again at method return type so method return type should be M.

Long answer:

I know you do know this definitions but sometimes we as human forget simple things. First we should consider what generics are created for, with generics we can create classes with different parameter types, this parameter types will be provided when they are extended by another class or when we create new instance of them with new() operator, so when we are writing our class we don't know the exact type for those parameter and we want to delay this decision until later, it is contradictory to something you are doing in your class because here your method is private and you can't change its implementation in your child class(the class which inherited from your class). But know we can change your implementation to something like this which will be compiled well:

public  class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
    private  M method1(){
        ...
    }
}

public class CommonMessage<T, X>{

}

public class MyMessage<T, X> extends CommonMessage<T, X>{

}
public class Model1{

}
public class Model2{

}

although this implementation will be compiled the problem is that when you are writing your private method(method1) you don't know what is the type of M at the time of writing this class because it will be passed when we want to create new instance of this class or when we inherit another class from this class. so what type of Object do you want to create and return in your method1? the only thing that you know here is that its type is M which extends CommonMessage but you don't know what the exact type of M is at the time of writing your private method(method1)!

And on the top of that you can't delegate this decision to your subclass(because this method is private). Now the question is that why it is allowed and compiled well when we don't know the exact type of M? for a moment forget this question I will make it clear after explaining correct approach. so what is the correct approach? Think about it, the person who write subclass does know exactly what the type of parameter M is and they can create appropriate instance of M in implementation of method1 to return from this method. so why not delegate this decision to subclass and making this method abstract? This completely make senses. in a nutshell we have some implementation like this:

public abstract  class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
    public abstract M method1();
}

public class CommonMessage<T, X>{

}

public class MyMessage<T, X> extends CommonMessage<T, X>{

}
public class Model1{

}
public class Model2{

}

now lets get back to our question why first program that I suggested to you compiled well? why we are allowed to have private method that its return type is generic that will be passed at instanciation or inheritance time? because there are a lot of situations that make it correct and appropriate. one situation is that our private method call another public method which return the appropriate type, like this:

public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
    private  M method1(){
        return method2();
    }
     abstract M method2();
}

public class CommonMessage<T, X>{

}

public class MyMessage<T, X> extends CommonMessage<T, X>{

}
public class Model1{

}
public class Model2{

}

Upvotes: 1

Related Questions