I have this question.
I have class UserImpl implements MyUser, YourUser
and class UsersGetterImpl implements MyUsersGetter, YourUsersGetter.
I want to implement a method inside UsersGetterImpl, which returns
List<MyUser> getUsers() for MyUsersGetterinterface, and
List<YourUser> getUsers() for YourUsersGetterinterface, but I cannot understand what have to be the return type of getUsers() inside the UsersGetterImpl class - probably it has to be something with wildcards (like List<? extends UserImpl> getUsers(), but not exactly, because this example won't work...)
It is hard to tell what you are asking, but according to the Java Language Specification:
In a situation such as this:
interface Fish { int getNumberOfScales(); }
interface StringBass { double getNumberOfScales(); }
class Bass implements Fish, StringBass {
// This declaration cannot be correct, no matter what type is used.
public ??? getNumberOfScales() { return 91; }
}
It is impossible to declare a method named getNumberOfScales with the same signature and return type as those of both the methods declared in interface Fish and in interface StringBass, because a class can have only one method with a given signature (§8.4). Therefore, it is impossible for a single class to implement both interface Fish and interface StringBass.
However, if both of your interfaces specify the same return type, then you can go ahead and implement that method. If MyUser and YourUser have a common ancestor then you could do List<? extends User> or if they have no commonality you can use simply use List<?>.
At that point though, you have to stop and consider if a common implementation is what you actually want. I suspect there may be a more elegant solution, if you provided us with more details about your problem.
Edit:
Based on your comment, you want something like...
interface MyUserGetter { List<? extends MyUser> getUsers(); }
interface YourUserGetter { List<? extends YourUser> getUsers(); }
class UserGetterImpl { List<? extends UserImpl> getUsers(); }
This is untested, and I'd guess has a 50% chance of working.
The architectural suggestion is that instead of having a single implementation for two interfaces you might actually want two implementations of one interface:
interface User {}
class MyUser implements User {}
class YourUser implements User {}
interface UserGetter { List<? extends User> getUsers(); }
The short answer is: it can't be done. You cannot have two methods whose signature differs only by return type, and you therefore cannot have one class implement two interfaces that define methods that only differ by return type.
The easy fix is to make MyUsersGetter and YourUsersGetter have methods with different names.
One possible workaround would be to have UsersGetterImpl not implement MyUsersGetter and YourUsersGetter directly, but to have delegates:
class UsersGetterImpl {
public MyUsersGetter getMyUsers () {
return new MyUsersGetter () {
public List<MyUsers> getUsers () {
//do stuff here
}
}
}
Related
Ok, I'll try to explain this as cleanly as I can.
I've created a generic abstract controller class that has a method hasCreatePermissions that looks something like this:
public abstract class ApplicationController<
AppEntity extends ApplicationEntity,
AppService extends ApplicationService<AppEntity>,
DTOManager extends ApplicationDTOManager
> {
// Other methods, properties, etc...
public boolean hasCreatePermissions(DTOManager.CreationRequest requestBody, Optional<UUID> requestingUser) {
return false;
}
}
Essentially, I want any class that overrides this method to be able to use its own DTOManager class as the parameter when it overrides this method.
The generic ApplicationDTOManager class looks like
public abstract class ApplicationDTOManager {
public abstract class CreationRequest {}
public abstract class CreationResponse {}
}
and any class that inherits ApplicationDTOManager can add classes that extend CreationRequest and CreationResponse for their own implementation of respective DTOs.
However, lets say I try to extend it with a UserResource class (assume UserDTOManager exists with an implementation for CreationRequest):
#RestController
public class UserResource extends ApplicationController<
User,
UserService<User>,
UserDTOManager
> {
#Override
public boolean hasCreatePermissions(UserDTOManager.CreationRequest requestBody, Optional<UUID> requestingUser) {
// Stuff
}
}
I'm told that this does not override any super class methods. Why? Is there any way to achieve this as I did not want to pass too many generics to my ApplicationController class, but also cannot have a constructor.
class ApplicationController<
AppEntity extends ApplicationEntity,
No, stop right there. This is declaring a type variable with the bound rules: "Must be either ApplicationEntity or any subtype thereof" and you named it AppEntity. This is going to make your head go in circles when you read the code later, 'I keep confusing reified types with type variables' comprises 95% of all confusion about generics. I know it seems unreadable, but there really is just only one way to go about it, and that is to use single capital letters for all your type vars. So let's fix that right now:
public abstract class ApplicationController<
E extends ApplicationEntity,
S extends ApplicationService<E>,
M extends ApplicationDTOManager> {
Which then immediately lets us see a big problem in the next line:
public boolean hasCreatePermissions(M.CreationRequest requestBody) {}
Of course that can't work. M is a type variable, at compile time the compiler has no idea what type it is. It could be bound to some type that doesn't even exist yet right now. You can't ask for a reified inner type on a type variable. You can of course simply talk about ApplicationDTOManager.CreationRequest and that's presumably what you want.
Alternatively, you're thinking that subtypes of ApplicationDTOManager may also want to subclass ApplicationDTOManager.CreationRequest. This is possible, but then all ApplicationDTOManager types need to carry their associated CreationRequest type as a type variable. We thus fix a few things:
public class ApplicationDTOManager<R extends ApplicationDTOManager.CreationRequest> {
public static class CreationRequest {}
}
You may have a non-static inner class named CreationRequest. I'm going to stop you again on that - non-static inners have an invisible inner field of their outer's type, and combining that invisible voodoo magic with generics just doesn't work. Don't do it. You can explicitly make that field if you must have it, and make a constructor that takes it. This is what javac generates for you if you don't add static to your inner classes. But by making it explicit, you take control of the generics, which you have to here, and avoid confusion which given the nature of the question seems pertinent.
I'm told that this does not override any super class methods. Why?
Java's method names include all their erased types. The name of this method:
class List<T extends Number> {
int hello(String name, boolean[] hi, T arg) throws SQLException {}
}
is, as far as the JVM is concerned, hello(Ljava/lang/String;[ZLjava/lang/Number;)I.
Yeah, no, really. javap -c -v a class file and you'll see it. (I is integer, [ is array, Z is boolean, and Ltxt; encodes ref type names in JVM style, e.g. with slashes and dollars instead of dots). It's written name(params)ret.
If you then subtype something and introduce a method whose erased JVM name is identical, you're overriding. If you don't, it is not an override. Merely an overload. Overrides are dynamically dispatched. But overloads are not - The names are all linked up at compile time. However, for any given 'JVM method name', the lookup is done dynamically based on the receiver type. In other words:
class Fruit {
void hi(Fruit f) { System.out.println("Fruit Fruit"); }
void hi(Apple a) { System.out.println("Fruit Apple"); }
}
class Apple extends Fruit {
void hi(Fruit f) { System.out.println("Apple Fruit"); }
void hi(Apple a) { System.out.println("Apple Apple"); }
}
Fruit f = new Fruit();
Fruit a = new Apple();
a.hi(a);
Will print Apple Fruit. You'd think it should print Apple Apple perhaps - we are calling apple's hi passing an apple, no? But the invocation a.hi(a) is invoking the method named hi(Lfruit;)V (because the type of a is Fruit). The receiver variable (a) has compile time type Fruit, but its real type is Apple. So, which of the hi(Lfruit;)V methods is chosen is done with dynamic dispatch - you get apple's hi(Fruit). Deciding between going with hi(Fruit) and hi(Apple) is done by the compiler only. Given that the type of the expression a is Fruit, you get hi(Fruit). The fact that if you resolve this expression, you get an object whose .getClass() returns Apple.class, doesn't change this.
Hence, what you wrote, does not override. Different name, even if you erase.
Toss generics in the mix and it gets funky. But you can do this.
public abstract class ApplicationDTOManager<I extends CreationRequest, O extends CreationResponse> {
public abstract static class CreationRequest {}
public abstract static class CreationResponse {}
}
public abstract class ApplicationController<
E extends ApplicationEntity,
S extends ApplicationService<AppEntity>,
I extends CreationRequest,
O extends CreationResponse,
M extends ApplicationDTOManager<I, O>
>
// heck that's probably too many, at some point generics aren't worth it
{
public abstract boolean hasCreatePermissions(I requestBody);
}
#RestController
public class UserResource extends ApplicationController<
User,
// UserService<User>, // this seems wrong!
UserService, // UserService should extends ApplicationService<User>
UserDTOManager.CreationRequest,
UserDTOManager.CreationResponse,
UserDTOManager> {
#Override
public boolean hasCreatePermissions(UserDTOManager.CreationRequest requestBody, Optional<UUID> requestingUser) {
// Stuff
}
}
Not sure all this is worth the pain, but, if you insist on linking all this together with generics, the above is the only way. You cannot express the notion 'has an inner type that is a subtype of CreationRequest' is a generics bound.
If you override a method you cannot have a different signature, If the method you override requires a DTOManager.CreateRequest you cannot use a child class within the override method.
You have to "support" all types of input that the parent method could take.
I believe that you need this because the permission validation relies on methods or fields of the child class. If so you should implement it inside the child class.
I have interface:
interface Identifable<T extends Serializable> {
T getID();
}
and class that implement this:
public class Cat implements Identifable<Long> {
public Long getID(){...};
}
everything works fine. so far. Now I want to create GenericDAO, why I cannot create this?:
public abstract GenericDAO<T extends Identifable<S>> {
T getByID(S id);
}
I can only declare my GenericDAO as this:
public abstract GenericDAO<T extends Identifable, S> {
T getById(S id);
}
And complete class:
public CatDAO extends GenericDAO<Cat, Long> {
Cat getById(Long id);
}
But i think it's useless, because I repeat information. I already declared, that Cat implements Identifable< Long >, so why do I must declare GenericDAO< Cat, Long >, not just GenericDAO< Cat > ?
In Java, every generic type must be specified. You can go without specifying any type, but you can't go without specifying just one.
Also, every generic type must be specified in the declaration. If you want to have class GenericDAO<T extends Identifable<U>>, you must add the generic type declaration for U to your class declaration like this (since U is actually a generic type here):
public abstract class GenericDAO<T extends Identifable<U>, U>
The following is partially off-topic, but you might find it useful.
I've noticed that in your definition of GenericDAO two generic types are not tied to each other. This might not be what you want.
What you have here is a particular case in which the two generics are matching (the Long type in the Cat and CatDAO definitions). Consider having these declarations:
public class Dog implements Identifable<Long>
public class DogDAO extends GenericDao<Dog, String>
This would force you to write the getById method in DogDAO method:
Dog getById(String id);
Your getId method in the Dog returns a Long so your getById method int DogDAO would have to compare Strings to Longs. This is valid thing to do, but it's a bit counter-intuitive. Having a getById method for DogDAO that takes a Long parameter makes more sense, since the Dogs IDs are actually Longs.
If you want to tie the two types together, you can define the GenericDAO class as:
public abstract class GenericDAO<T extends Identifable<S>, S>
You still have to specify the second parameter, but at least the compiler can help you make sure that the types are matching.
Try this:
public abstract class GenericDAO<S extends Serializable, T extends Identifable<S>> {
abstract T getByID(S id);
}
This is an existing interface:
public interface MyInterface<T, U> {
public T foo(U u);
}
I want to implement this interface under the assumption that T and U are the same type. I thought maybe I could leave the type parameters in as they are, and then as long as I only ever instantiate this particular implementation with two of the same type, that it might work:
public class MyOuterClass<A> {
public class MyClass<T, U> implements MyInterface<T, U> {
#Override
public T foo(U u) {
return u; //error here
}
//even though in the only instantiation of MyClass, T and U are the same
private MyClass<A, A> myInstance = new MyClass<A, A>();
}
But, perhaps unsurprisingly, this doesn't work, as types T and U are incompatible.
So then I thought maybe I could change MyClass to specify that its types would always be the same, by changing it to something like MyClass<A, A> implements MyInterface<A, A> or similar, but I get errors saying that T is already defined.
Is there a way to implement MyClass so that its two types will be the same?
(I'm more of a C++ guy than Java, so sorry if I'm missing something fundamental about Java's generic's here.)
Your myclass needs to look like this:
public class MyClass<T> implements MyInterface<T, T> {
#Override
public T foo(T in) {
return in;
}
}
Let's review what your suggested class definition does:
public class MyClass<T, U> implements MyInterface<T, U>
In this code, T and U do two things each:
in the first occurance they define a type variable of your MyClass class
in the second occurance they specify the concrete type of the MyInterface class
Since inside the body of your class T and U are unbounded type variables (i.e. nothing is known about the actual types), they are assumed to be incompatible.
By having only a single type variable in your MyClass you make your assumption explicit: there's only a single type, and I'm using it for both types of the interface.
Last but not least: remember that the compilation of a type is complete once the source is fully handled. In other words: contrary to what C++ does, "instantiation" of a generic type ("template type" or similar in C++; Sorry for my rusty terminology) does not handle. MyClass<Foo> and MyClass<Bar> are the same type, as far as the JVM is concerned (only the compiler actually distinguishes them).
Define a single type parameter for MyClass:
class MyOuterClass<A> {
public class MyClass<T> implements MyInterface<T, T> {
public T foo(T u) {
return u;
}
}
// Need only one 'A' here.
private MyClass<A> myInstance = new MyClass<A>();
}
When you say
public class MyClass<T> implements MyInterface<T, T> {
... you are defining one generic variable for MyClass and you are saying that it fulfills both the roles T and U in MyInterface.
I'm having difficulty using generics for a redesign/refactoring I'm doing on an existing design.
public interface DataDto {
// some data here
}
public interface SetDto<MyDataDto extends DataDto> {
List<MyDataDto> getData();
}
public interface Results<MySetDto extends SetDto<DataDto>> {
MySetDto getResults();
}
public interface MyProblemInterface<MyDataDto extends DataDto,
MySetDto extends SetDto<MyDataDto>,
MyResults extends Results<MySetDto>> {
// some stuff here
}
My problem is that I get the following error for MyProblemInterface:
Bound mismatch: The type MySetDto is not a valid substitute for the
bounded parameter <MySetDto extends SetDto<DataDto>> of the type
Results<MySetDto>
I admit my experience with generics is somewhat limited, but basically I'm trying to enforce that all three of the types in MyProblemInterface are the same "type". For example, if I have ADataDto, BDataDto, ASetDto<ADataDto>, BSetDto<BDataDto>, AResults<ASetDto>, BResults<BSetDto>, I want to ensure a class can't implement MyProblemInterface in a manner like AMyProblemInterface<ADataDto, ASetDto, BResults>. I would think that since MySetDto extends SetDto<MyDataDto> just fine, I could continue to take that further, but I'm apparently wrong.
Thank you for any help.
You want too much from Java generics.
It would be simpler to declare your interface as following:
public interface MyProblemInterface<MyDataDto extends DataDto>
And then force method to use SetDto<MyDataDto> and Results<MySetDto>.
By using generics in class/interface declaration you specify some kind of variety which is determined later in definition. But in your case you said that SetDto and Results will always have MyDataDto as parameter, so there is no variety.
Shouldn't it be something like this instead, and you add the actual classes only when implementing the interfaces.
Updated the code, because I forgot to add the right Results definition. This should work.
public interface DataDto {
// some data here
}
public interface SetDto<T extends DataDto> {
List<T> getData();
}
public interface Results<T extends SetDto<? extends DataDto>> {
T getResults();
}
public interface MyProblemInterface<T extends DataDto, E extends SetDto<T>, K extends Results<E>> {
// some stuff here
}
Is there a way in java to specify, that the type parameter of a generic class must be an interface (not just extending it!)
What I want to do is the following:
public class MyClass<X extends SomeInterface, Y extends SomeOtherClass & X>
Meaning that Y must be a subclass of SomeOtherClass AND implement X.
What I currently get by the compiler is
The type X is not an interface; it cannot be specified as a bounded parameter
So, how can I tell the compiler that X must always be an interface?
Edit:
OK, I guess I oversimplified my problem a bit. Let's use my actual application domain to make it more clear:
I have an API for representing diagrams. A Diagram contains Node and Edge objects. All these three classes implement the Shape interface. Shapes may have child shapes, a parent shape and belong to a diagram.
The thing is, that I need to make two versions of this API: one open-source with just basic functionality and an extended one with more features. However, the extended API must only provide methods, which return the extended types (ExtendedDiagram, ExtendedNode, ExtendedEdge and (here comes the problem) ExtendedShape).
So I have something like this:
/* BASIC CLASSES */
public interface Shape<X extends Shape<X,Y>, Y extends Diagram<X,Y>>{
public List<X> getChildShapes();
public X getParent();
public Y getDiagram();
...
}
public class Diagram<X extends Shape<X,Y>, Y extends Diagram<X,Y>> implements Shape<X,Y>{...}
public class Edge<X extends Shape<X,Y>, Y extends Diagram<X,Y>> implements Shape<X,Y>{...}
...
/* EXTENDED CLASSES */
public interface ExtendedShape extends Shape<ExtendedShape,ExtendedDiagram> { ... }
public class ExtendedDiagram extends Diagram<ExtendedShape,ExtenedDiagram> implements ExtendedShape { ... }
public class ExtendedEdge extends Edge<ExtendedShape,ExtenedDiagram> implements ExtendedShape { ... }
...
The extended API works fine and the basic API code gives some warnings, but the main problem occurs when using the basic API:
public class SomeImporter<X extends Shape<X,Y>, Y extends Diagram<X,Y>, E extends Edge<X,Y>>{
private Y diagram;
public void addNewEdge(E newEdge){
diagram.addChildShape(newEdge);
...
That last line gives me the following warning:
The method addChildShape(X) in the type Diagram is not applicable for the arguments (E)
So now, I would just like to specify that E also needs to implement X and all would be fine - I hope ;)
Does all that make sense? Do you guys know a way to do that? Or is there even a better way to get the extended API with the said restrictions?
Thanks for sticking with me, any help is greatly appreciated!
You can use:
class Foo<T extends Number & Comparable> {...}
A class Foo with one type parameter, T. Foo must be instantiated with a type that is a subtype of Number and that implements Comparable.
In the generics context, <Type extends IInterface> handles both extends and implements. Here's an example:
public class GenericsTest<S extends Runnable> {
public static void main(String[] args) {
GenericsTest<GT> t = new GenericsTest<GT>();
GenericsTest<GT2> t2 = new GenericsTest<GT>();
}
}
class GT implements Runnable{
public void run() {
}
}
class GT2 {
}
GenericsTest will accept GT because it implements Runnable. GT2 does not, therefore it fails when trying to compile that second GenericsTest instantiation.
Maybe you can simplify your model a bit: too much generics become quickly a real pain in terms of readability, and that's quite an issue if you define a public API. Usually, if you can't understand anymore what should be inside the brackets, then you're going too far for your need - and you can't expect users to understand it better than yourself...
Anyway, in order to make your code compile, you may try defining something like this, in the Shape type:
public <S extends Shape<?,?>> void addChildShape(S shape);
That should do it.
HTH
You wrote the following:
public interface Shape<X extends Shape<X,Y>, Y extends Diagram<X,Y>>{
public List<X> getChildShapes();
public X getParent();
public Y getDiagram();
...
}
I would advise, at the minimum, getting rid of the X type variable, as follows:
public interface Shape<Y>{
public List<Shape<Y>> getChildShapes();
public Shape<Y> getParent();
public Diagram<Y> getDiagram();
...
}
The reason being is that what you originally wrote suffers from a potentially unbounded recursive nesting of the type parameters. A shape may be nested within a parent shape, which may be nested within another, all of which must be accounted for in the type signature... not a good recipe for readability. Well, it doesn't happen quite that way in your example, in which you declare "Shape<X>" instead of "Shape<Shape<X>>" but that's the direction you're going in, if you ever wanted to actually use Shape on its own...
I would probably also recommend going one step further and getting rid of the Y variable for similar reasons. Java generics don't cope very well with this sort of composition. When attempting to enforce static types for this type of modelling via generics, I've found that the type system starts to break down when you start to extend things later on.
It's typical of the Animal/Dog problem... Animal has a getChildren(), but Dog's children must also be Dogs... Java doesn't cope with this well because (in part due to the lack of abstract types as in languages like Scala, but I'm not saying you should rush off and use Scala for this problem either) the type variables have to start being declared in all sorts of places where they don't really belong.
Use a pre-processor to generate the "reduced" version of your code. Using apt and annotations might be a nice way to do it.
I might be WAY off base here, but my understanding of generics is a little different.
I am asking someone to correct me if I am wrong.
IMO -
This is a very confusing structure that you have. You have SubClasses of Shape being referenced infinitely it looks like.
Your Shape interface is utilized in the same manner as a HashMap, but I have never seen a HashMap do what you are trying to do, eventually you have to have X be a class in Shape. Otherwise you are doing HashMap
If you always want X to be a "IS A" relationship to an interface it won't happen. That is not what generics are for. Generics are used to apply methods to multiple Objects, and interfaces cannot be Objects. Interfaces define a contract between a client and a class. All you can do with the is say that you will accept any Object that implements Runnable, because all or some of your methods are required to utilize the Runnable interface methods. Otherwise if you don't specify and you define as , then your contract between your class with the client can produce unexpected behavior and cause either the wrong return value or an exception to be thrown.
For example:
public interface Animal {
void eat();
void speak();
}
public interface Dog extends Animal {
void scratch();
void sniff();
}
public interface Cat extends Animal {
void sleep();
void stretch();
}
public GoldenRetriever implements Dog {
public GoldenRetriever() { }
void eat() {
System.out.println("I like my Kibbles!");
}
void speak() {
System.out.println("Rufff!");
}
void scratch() {
System.out.println("I hate this collar.");
}
void sniff() {
System.out.println("Ummmm?");
}
}
public Tiger implements Cat {
public Tiger() { }
void eat() {
System.out.println("This meat is tasty.");
}
void speak() {
System.out.println("Roar!");
}
void sleep() {
System.out.println("Yawn.");
}
void stretch() {
System.out.println("Mmmmmm.");
}
}
Now if you did this class you can expect that you CAN always call 'speak()' & 'sniff()'
public class Kingdom<X extends Dog> {
public Kingdom(X dog) {
dog.toString();
dog.speak();
dog.sniff();
}
}
However, if you did this you CANNOT ALWAYS call 'speak()' & 'sniff()'
public class Kingdom<X> {
public Kingdom(X object) {
object.toString();
object.speak();
object.sniff();
}
}
CONCLUSION:
Generics give you the ability to utilize methods on a wide range of objects, not interfaces. Your final entry into a generic MUST be a type of Object.
The reserved word “extends” as along with a type parameter T is used to specify a bound.
‘…in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces).’
[ https://docs.oracle.com/javase/tutorial/java/generics/bounded.html ]
In short, “extends” can only be used to specify a bound (whether a class or an interface) for some class type parameter T and not any interface type parameter T.
In your case,
public class MyClass<X extends SomeInterface, Y extends SomeOtherClass & X>
The compiler resolves X to be a class. For the second occurrence of X along with the type parameter Y (which clearly needs to be a class anyway), it requires X to be an interface. Since it has already resolved X to be class, it signals the error for the second occurrence of X,
The type X is not an interface;
Further, had X been specified in the first occurrence as an unbounded parameter, the compiler would have resolved it to be either a class or an interface and it would’ve considered the second occurrence of X to be a possible interface and thus allowed compilation. Since it was not so, the compiler clarifies,
it cannot be specified as a bounded parameter