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)
Related
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{
}
This question already has answers here:
When do we use interface extends interface
(3 answers)
Closed 6 years ago.
I have a question about java's use of an interface. I initially thought we can only implement interfaces in a given class. But in this code example,
public interface InterW {
}
public interface InterX<T> {
}
public class ClassY {
}
public class ClassZ {
}
Why is this a valid answer?
public class ClassB<T extends InterX<ClassY>> extends ClassZ
implements InterW {
}
Can a type parameter extend an interface?
And why is this one wrong?
public class ClassE<T implements InterW> extends ClassZ {
}
Please see the Oracle Documentation on Bounded Type Parameters
Particularly -
To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound ..... Note that, in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces).
Can a interface be ever be extended?
An interface can only extends interface .In fact An interface can extends multiple interfaces.
public interface Interface4 extends Interface1 , Interface2 ,
Interface3 { // methods }
coming back to you second question
And why is this one wrong?
`public class ClassE<T implements InterW> extends ClassZ {
}`
As user2615897 mentioned
To declare a bounded type parameter, list the type parameter's name,
followed by the extends keyword, followed by its upper bound .....
Note that, in this context, extends is used in a general sense to mean
either "extends" (as in classes) or "implements" (as in interfaces).
As per JVM, in context of upper bound whether you use extends or implements both does the same thing. But JVN allows the syntax extends to avoid confusion
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.
Suppose i have an interface and two extending classes, like below;
public interface UpdateHelper<T>{
List<T> getItemsToOperate();
}
public class ProfileUpdateHelper implements UpdateHelper<Profile>{
//class logic
}
public class PlayerUpdateHelper implements UpdateHelper<Player>{
//class logic
}
Player and Profile are two concrete classes. When i design my classes like above everything is fine. But i would like to introduce another abstraction layer between concrete Profile and Player classes such as;
public abstract class Updatable{
//common attributes will be here
}
public class Player extends Updatable{
}
public class Profile extends Updatable{
}
And use my helper classes like that;
public interface UpdateHelper<T>{
List<T> getItemsToOperate();
}
public class ItemUpdateHelper<? extends Updatable> implements UpdateHelper<Updatable>{
//class logic
}
I think I should use wildcards since any class instance extending updatable can be used with helper classes and it should not matter which sub-class instance is being used.
But when i write like above i get an unexpected wildcard error just after class names and code won't get compiled. Am i missing something, doing something wrong or something like that can't be done in java. By the way I am using java 8.
You can't use wildcards in class declaration. Instead, you pass a type parameter like T:
public class ItemUpdateHelper<T extends Updatable> implements UpdateHelper<Updatable>{
...
}
You can specify concrete implementation of Updatable:
ItemUpdateHelper<Player> playerHelper = new ItemUpdateHelper<>();
ItemUpdateHelper<Profile> profileHelper = new ItemUpdateHelper<>();
or not:
ItemUpdateHelper helper = new ItemUpdateHelper();
You would want to implement it like,
public class ItemUpdateHelper<T extends Updatable> implements UpdateHelper<T>{
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to reference a nested generic parameter in java?
A quick question on Java generics if I may. Is there syntax for declaring a generic class-wide type that is NOT used as a generic parameter for instantiation. For example:
public class <U extends FooUType> BarType<T extends FooType<U>>{
public U getU(){return U;}
}
To create a BarType I want to write the following, which in itself contains U, but I don't want to have to specify U separately. So:
BarType<SomeT<FooUType>> instance
We get the type of U implicitly from the parameterized SomeT without having to specify U separately. As opposed to :
public class BarType<U extends FooUType, T extends FooType<U>>
which would require:
BarType<FooUType,SomeT<FooUType>>
I guess I'm looking for something akin to the same idea in methods:
public <U> boolean StupidMethod(String s){
...
}
I would rather not use <? extends FooUType> as this leads to problems with method return types inside the class that return <U extends FooUType> U.
Many thanks for the clarification!
As the comments said, this isn't possible.
I would rather not use <? extends FooUType> as this leads to problems with method return types inside the class that return <U extends FooUType> U.
So, here you're saying that some methods of the class return U... yet you don't want to have U as a type parameter. Well, you can't have it both ways. Either have this:
public class BarType<T extends FooType<U>, U extends FooUType>{
public U getU() { ... }
}
Or this:
public class BarType<T extends FooType<? extends FooUType>>{
public FooUType getU() { ... }
}
If it's just the noisy instantiation you're concerned with, you can use new BarType<> where applicable with Java 7. Without Java 7, declare a factory method so the callers can use type inference:
public static <T extends FooType<U>, U extends FooUType> BarType<T, U> make() {
return new BarType<T, U>();
}
Thanks all,
I went for a different solution in the end. Basically the class I was trying to hide the U in was abstract and so I added U as a generic parameter as there is no way round this. I then created the concrete classes that extend this and had them fill in the type of U silently so that the caller wouldn't need to bloat their code.
Something like this:
public abstract class MyAbsClass<U extends Foo, T extends Bar<U>>{...}
public class ConcreteClass<T extends SomeBar> extends MyAbsClass<SilentUType, T>
where SomeBar is not parameterized. The user can then just instantiate with T:
new ConcreteClass<SomeDerivedBar>()
This worked for my scenario neatly, so I hope it helps others.