Java : generic type with type parameters? - java

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() {
....
}
}

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{
}

Related

Whats does SomeClass<T extends SomeClass<T>> mean? [duplicate]

This question already has answers here:
Self bounded generics
(2 answers)
Closed 1 year ago.
I just saw a class declaration in our codebase that looks like this:
public abstract class SomeClass<T extends SomeClass<T>> implements Cloneable {
...
}
After learning from a couple of tutorials on Java generics, now I understand stuff like SomeClass<T extends Comparable<T>.
However, SomeClass<T extends SomeClass<T>> still doesn't make sense to me. Apparently, T must derive from SomeClass<T>... but SomeClass has not been declared yet! What is happening here?
Any help is appreciated!
Most probably, inside the abstract class there something like this:
public abstract class SomeClass<T extends SomeClass<T>> implements Cloneable {
public abstract T someMethod(); //<-- variable return type should be the implementing class itself
public abstract int someOtherMethod(T someInstance); //<-- variable parameter type should be the implementing class itself
}
With such declaration, when you extend the class SomeClass with something concrete, let's say SomeConcreteClass, then you'll have:
public class SomeConcreteClass extends SomeClass<SomeConcreteClass> {
#Override
public SomeConcreteClass someMethod() {
//implementation that returns SomeConcreteClass
}
#Override
public int someOtherMethod(SomeConcreteClass instance) {
//implementation that takes in parameter this type of class
}
}
When you declare an abstract class like that, you basically ask to self-reference the child class in the parameter type.
Of course you may also use another child (it would still be inside bounds as long as it extends SomeClass), but it's a rare use case (I'll never seen it personally)

Java factory uses generics and Supplier interface, but still needs typecasts, something is not right

I'm trying to use generics and a Supplier to avoid needing to typecast the result of my static factory method but failing. I think I'm close, can someone point out what I'm doing wrong here?
Here is the parameterized interface IManager:
public interface IManager<C extends IConfigObject> {
Here is an abstract base class AbstractManager, which includes the static factory method:
public abstract class AbstractManager<C extends IConfigObject> implements IManager<C> {
....
public static <C extends IConfigObject> AbstractManager<C> getInstance(Supplier<? extends AbstractManager<C>> supplier) {
Next, here is a concrete implementation called MyManager which is parameterized with MyConfigObject, which in turn implements IConfigObject:
public final class MyManager extends AbstractManager<MyConfigObject> {
And finally, the main() code:
Supplier<MyManager> supplier = MyManager::new;
MyManager manager = (MyManager) AbstractManager.getInstance(supplier);
If I don't have the cast in there, I get a compiler error:
Type mismatch: cannot convert from
AbstractManager to MyManager
Any suggestions?
Your problem is here: Supplier<? extends AbstractManager<C>>. By using the wildcard, you're saying "I don't care about the actual type" but you do.
The key here is to first use two type parameters, the second of which relies on the first one (I used M for "manager"):
public static <C extends IConfigObject, M extends AbstractManager<C>>
M getInstance(Supplier<M> supplier)
{
// ...
}
If you're not using C in the method body, you could refactor it to:
public static <M extends AbstractManager<? extends IConfigObject>>
M getInstance(Supplier<M> supplier)
{
// ...
}

Interface extending a class

Let's say that I have an interface, and all classes that implement that interface also extend a certain super class.
public class SuperClass {
public void someMethod() {...}
}
public interface MyInterface {
void someOtherMethod();
}
//many (but not all) sub classes do this
public class SubClass extends SuperClass implements MyInterface {
#Override
public void someOtherMethod() {...}
}
Then if I'm dealing with an object of type MyInterface and I don't know the specific sub class, I have to hold two references to the same object:
MyInterface someObject = ...;
SuperClass someObjectCopy = (SuperClass) someObject; //will never throw ClassCastException
someObjectCopy.someMethod();
someObject.someOtherMethod();
I tried making the interface extend the super class, but it's a compiler error:
public interface MyInterface extends SuperClass {} //compiler error
I also thought of combining the interface and the super class into an abstract class like so:
public abstract class NewSuperClass {
public void someMethod();
public abstract void someOtherMethod();
}
But then i can't have a sub class that doesn't want to implement someOtherMethod().
So is there a way to signify that every class that implements an interface also extends a certain class, or do I have no choice but to carry around two references to the same object?
I think that the only solution you have would be to have a reference to both, but this indicates that you have a design flaw somewhere. The reason I say is because you should think of an interface as something that your implementing classes will always need. For example, a Car and Airplane both need a Drive() interface. A design reconsideration is probably worth your time. However, if you still want to follow that path, you can do the following:
public class ClassA {
public void methodA(){};
}
public abstract class ClassB extends Class A{
public void methodB();
}
After you have the above setup, you can now reference an object that has the two methods by doing the following:
ClassB classB = new ClassB();
classB.methodA();
classB.methodB();
Now you don't actually have to actually use two pointers to the same object.

Abstract Inheriting form of Comparable Interface

I understand how to use the Comparable<T> interface, but in this specific example, I'm wondering if there is a way to require the inheriting Class from an Abstract Class (which implements the Comparable<T> interface) to be Comparable against itself.
Let me reiterate, there is an Abstract Class that implements the Comparable Interface:
public abstract class MyAbstractClass implements Comparable<MyAbstractClass>
And a Class which inherits from this Abstract Class:
public class MyClass extends MyAbstractClass
Typically with this setup, the following method is required to satisfy the Comparable Interface:
public int compareTo(MyAbstractClass otherAbstractObject)
This requires me to make the following cast:
public int compareTo(MyAbstractClass otherAbstractObject)
{
MyClass otherObject = (MyClass) otherAbstractObject;
// Comparison...
return result;
}
Given the fact that this cast could easily fail by trying to use a different child of MyAbstractClass, I would like to be able to define my Abstract Class to accept the following method:
public int compareTo(MyClass otherMyObject)
{
// Comparison...
return result;
}
And ideas on how to accomplish this? Or is it simply not possible?
You can define MyAbstractClass using generics as follows:
public abstract class MyAbstractClass<T extends MyAbstractClass<T>>
implements Comparable<T> {
Then you can define subclasses such as
public class MyClass extends MyAbstractClass<MyClass>
which allow you to define the compareTo method like this:
public int compareTo(MyClass otherMyClass)
However, that doesn't prevent anyone from writing a subclass that doesn't conform to the pattern:
public class SneakyClass extends MyAbstractClass<MyClass>
which would also define the compareTo method similarly:
public int compareTo(MyClass otherMyClass)
Note: There's nothing that can force the generic type parameter of a class to equal the class on which it's defined; the best you can do is to enforce an upper bound on the abstract class, to at least force it to be some kind of MyAbstractClass.

Java generics - naming actual types of actual type

Given an interface like this
public interface MyInterface1<T extends MyAbstractClass> {
...
}
I want to make another interface MyInterface2 taking a MyInterface1 as a generic type and in MyInterface2 I want to reference the actual types of the actual MyInterface1
public interface MyInterface2<INTERFACE extends MyInterface1<MYCLASS>> {
MYCLASS returnInstanceOfMyClass();
}
So I want to say that method "returnInstanceOfMyClass" returns the actual T of the actual MyInterface1 given to MyInterface2.
The thing is that I am not allowed to write the following
public interface MyInterface2<INTERFACE extends MyInterface1<MYCLASS>> {
I am allowed to write
public interface MyInterface2<INTERFACE extends MyInterface1<?>> {
but then I am not able to reference the actual type of T in MyInterface1 in the method signature in MyInterface2 - because I have given it no name to be used when referencing.
I want to be able to do the following in a type-safe way
class MyClass extends MyAbstractClass {
...
}
MyClass c = new MyInterface2<MyInterface1<MyClass>>.returnInstanceOfMyClass();
No casting to MyClass should be necessary, because it can see that the actual class of MyInterface1 given to MyInterface2 is MyClass, and that is what is returned from returnInstanceOfMyClass.
How to do that?
You need a second generic parameter:
public interface MyInterface2<U estends MyAbstractClass, T extends MyInterface1<U>> {
U returnInstanceOfMyClass();
}

Categories