composition of generic types in java - java

Let's say I'm defining a class User, which has a generic type which extends Principal
public abstract class User<P extends Principal> {
}
And I have an action base class which should be parameterized with an user:
public abstract class Action<U extends User<Principal>> {
}
Those two classes are on muy codebase. Now, I want to use them on an specific application, so I create an implementation for Principal and User:
public class MyPrincipal implements Principal {
public String getName() {
return "Administrator";
}
}
public class MyUser extends User<MyPrincipal>{
}
Once I have my user, I want to use it on an action
public class MyAction extends Action<MyUser>{
}
This last class does not compile. It complais that :
Bound mismatch: The type MyUser is not a valid substitute for the bounded parameter <U extends User<Principal>> of the type Action<U>
What I want is to enforce that all classes extending MyAction should be parameterized with an object that extends User, and also is parameterized by an object which implements Principal. What I'm missing?

Currently, the bound on your Action class says - U extends User<Principal>. Since MyUser deoesn't extend a User<Principal>, but a User<MyPrincipal>, it won't work as you expected. A User<MyPrincipal> is not a User<Principal> (distinct types).
You can introduce another type parameter in your Action class, and use that in bounds of U:
public abstract class Action<P extends Principal, U extends User<P>> {
}
and now, you can create your MyAction like this:
public class MyAction extends Action<MyPrincipal, MyUser>{
}
Or you can also modify your class using wildcard bound:
public abstract class Action<U extends User<? extends Principal>> {
}
This way you won't need another type parameter:
public class MyAction extends Action<MyUser>{
}
References:
Java Generics FAQs
Can I use a type parameter as part of its own bounds?

Change Action's signature to this (I tested this in Eclipse and it compiles):
public abstract class Action<U extends User<? extends Principal>>
By doing this, you're saying that any type of Principal is okay, not just base-type Principal objects (which of course can't be instantiated).

Related

In an interface, I first declare a generic that extends an interface, then a generic that extends the first generic along with another interface

For example,
public interface Foo<T extends Blackness, S extends T & Whiteness> { }
Error: Type parameter cannot be followed by other bounds
T extends Blackness and S extends T so S inherently extends Blackness. The only other contingency is that S must also extends Whiteness. Because of this restriction, S must be an extension of T but also implement the functionality of Whiteness. Because of this, you will likely have to provide the type T. It's not possible for S to have multiple bounded types, which is why a sub-interface is required that implements both. What you're trying to do doesn't make logical sense. Refer to this.
public interface Foo<T extends Blackness, S extends BlackAndWhiteness<T>> {
}
public interface BlackAndWhiteness<T extends Blackness> extends Whiteness, Blackness {
}
interface Blackness {
}
interface Whiteness {
}

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

Java cannot be inherited with different arguments

I'm having trouble actually inheriting the interface. I keep ending up with the error
error: NameableContainer cannot be inherited with different arguments: < Friend> and <>
I have the following interfaces:
public interface Nameable
public interface Name
public interface Friend extends Nameable
public interface NameableContainer<T extends Nameable> {
void add(Name name, Name prevName);
void remove(Nameable nameable);
T findByName(Name name);
}
public interface FriendContainer extends NameableContainer<Friend>
I also have an abstract class that inherits NameableContainer.
public abstract class NameableMap implements NameableContainer {
public void add(Name name, Name prevName) { /* do stuff*/ }
public void remove(Nameable nameable) { /* do stuff*/ }
public Nameable findByName(Name name) { /* do stuff*/ }
}
And finally, trying to put these all together
public class Friends extends NameableMap implements FriendContainer
What am I missing?
You are using raw types when you say
public abstract class NameableMap implements NameableContainer
That throws everything off in the compiler; raw types are an error unless your code was originally written for java 1.4 or earlier. When you implement an interface that specifies a type argument, you either need to provide a concrete type, or if that isn't known yet, you can introduce another type parameter and pass it to the supertype.
See: What is a raw type and why shouldn't we use it?
So you specify a variable generic type parameter when you implement NameableContainer (since you don't know the concrete type yet as NameableMap should also work for all Nameables.
public abstract class NameableMap<T extends Nameable> implements NameableContainer<T>
// ^^^^^^^^^^^^^^^^^^^^ ^^^
move all the code from the entire program to one class and put it onto one line

Class of unknown type with an upper bound

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

Generic type subclass

I have the following generic class:
public class Evalutor<T>{
}
I would like to create the type called NumberEvalutor as follows:
public class NumberEvalutor<T> extends Evalutor<T extends Number>{ //Syntax error on token "extends", , expected
}
But I couldn't do it that way. Maybe you can advice another type-safe way?
Try with:
public class NumberEvalutor<T extends Number> extends Evalutor<T> {
}
Type parameters on class-level (like <T extends Number>) must be introduced after the class name and can be referred in the super-class/super-interface list. Otherwise, there won't be a way to (explicitly) specify their runtime value when creating class instances.
This one should work :)
public class NumberEvaluator<T extends Number> extends Evaluator<T> {
}

Categories