Java Generics restrict to interface - java

I'm not sure if this is possible or not, but what I want to accomplish is this:
public static <A,B extends SomeClass & A> B makeB(A thing) {...}
Essentially, using a reflection/generation driven process, I want to provide a thing of type B, where B is of class SomeClass and implements interface A, and A is user-supplied through Generics.
I am not asking about the mechanics of generating B - I have that under control. What I'm looking for is a way to restrict generic type argument <A> to interfaces, not classes, so that I can use the syntax B extends SomeClass & A for clean type safety.
Is this possible? Is anyone aware of an alternative approach to this problem?
Edit: I guess I didn't express myself very clearly, as it seems to be causing confusion in the comments:
B is intended to be a placeholder for a wildcard, so that the client can get a single object that is both a SomeClass and an A without having to do casting based on trust. The client will not have access to the name of the actual class that implements SomeClass and A, because it's being generated at compile time, hence this issue regarding type safety.

It's impossible to impose such a compile-time restriction. Generic type parameters are stand-ins for reference types; they make no distinction between class types and interface types. The fact that additional bounds in a type parameter's declaration must be interface types is merely incidental - your strategy to leverage this as a means to impute a type as an interface was clever, but it's defeated by the limitation that type parameters can't be used in multiple bounds.
Your only options are to settle for a runtime check using Class.isInterface() like Louis Wasserman pointed out, or to leave it up to the caller to be responsible with what it passes in. Either way, make sure to clearly document the method's expectations and behavior.
B is intended to be a placeholder for a wildcard, so that the client can get a single object that is both a SomeClass and an A without having to do casting based on trust. The client will not have access to the name of the actual class that implements SomeClass and A
This seems like a contradiction to me. There's no point to declaring B if the caller can't possibly know what it evaluates to. Remember: the caller of a generic method provides its type arguments. So a caller deciding B without anything to base it on can only be guessing - and that can never be type-safe.
It seems like what you really want your method to return is some type that is both a SomeClass and an A, but this is tricky because they don't share a common supertype:
public static <A> SomeClass&A makeSomeClass(A thing) {...}
(this is nonsensical syntax for demonstration purposes only)
As a workaround, consider alternative ways to represent both a SomeClass and some interface type. For example the candidate interfaces could have a common method for returning a SomeClass:
public interface IsSomeClass {
SomeClass asSomeClass();
}
public interface Foo extends IsSomeClass { }
The implementation of asSomeClass would in fact just return this. Then you could do:
public static <A extends IsSomeClass> A makeSomeClass(Class<A> type) {...}
And the caller of that method would be able to use the returned object as either type:
final Foo foo = makeSomeClass(Foo.class);
final SomeClass someClass = foo.asSomeClass();
If the interfaces themselves can't be modified, then another option is to use a wrapper class and composition instead:
final class SomeClassWrapper<A> {
private final SomeClass someClass;
private final A a;
//constructor and getters, etc.
}
And your method would return a wrapper instance instead, assigning the implementation instance to both someClass and a:
public static <A> SomeClassWrapper<A> makeSomeClass(Class<A> type) {...}

If SomeClass is always a class, the A in <B extends SomeClass & A> can only be an interface, because there is no multiple inheritance in Java. The only way & A can be satisfied is if A is an interface.

I think the problem here is that you want to return a B from this method.
You specify B as a type parameter, but it never appears anywhere else in the method signature.
How is the compiler supposed to infer the return type from the arguments????
There is no opportunity for the client code to specify what B is.
It seems like you should return either a SomeClass or an A.
Either one can be a B under the hood, but should appear as a SomeClass or an A to the client code.

Related

Why won't Java let you inherit from a generic type-variable?

public class MyClass<T> extends T {...}
The above declaration will fail to compile with the error:
error: unexpected type
class MyClass<T> extends T {}
^
required: class
found: type parameter T
where T is a type-variable:
T declared in class MyClass
I can't really think of a reason for this to happen, so I am wondering if someone can shed some light on why it is that Java won't let you inherit from a generic type-variable.
The most obvious reason I can think of isn't even about type-erasure; it is the fact that when you make A a subclass of B, the Java compiler needs to know what constructors B has. If a class does not have a no-arguments constructor, then its sub-classes must call one of its defined constructors. But when you declare
public class MyClass<T> extends T {...}
It is absolutely impossible for the compiler to know what the super constructors are, since T is not fixed at compile-time (that's the whole point of generics after all), which is a situation that cannot be allowed in Java.
Java has quite a lot of language restrictions unlike C++ for example. What you want is not possible for many reasons listed in the comments (T might be final or have abstract methods). However, you are allowed to extend from a supertype having the generic type parameter:
public class MyClass<T> extends AnotherClass<T>
You might find the following alternative interesting:
public class MyClass<T extends AnotherClass> extends AnotherClass
What you want to do does make not much sense.
Your question is not so weird as it may look like :) Consider how would you deal with following:
Suppose your real class for T has a single constructor with 3 parameters. How would you implement the constructor of inherited class, if you don't know how to call the super constructor?
Suppose your real class for T has public final methods and you have defined methods with the same signature in the inherited class. What method would your object have? You cannot resolve such conflict.
Simple deductions based on your question.
T is a type.
MyClass extends T - MyClass is enhanced version of T.
MyClass < T> extends T - MyClass is enhanced T, but only for Type T.
there is no reason to state ' I extend T but only for type T'.
If you extend T, MyClass is already a Type of T & definitely not some X,Y or Z.
Generics are needed if you want to ensure Type safety, if you extend it is already type safe.

Regarding Java subclasses inheriting methods that return "this"

Have a class Car with a public method
public Car myself() {
return this;
}
Have a subclass Ferrari, and a variable foo that contains a Ferrari object.
Finally,
Ferrari bar = foo.myself();
This will warn you, because the method myself() returns a Car object, rather than the expected Ferrari.
Note: I know that the example is stupid because you'd just do bar = foo. It's just an example.
Solutions:
Override the myself() method in Ferrari.
Cast the Car object to a Ferrari object when assigning bar.
Both solutions work and I am okay with that. However, the first one is undesirable when you have several subclasses of Car. I feel that overriding a method over and over defeats the point of inheriting it. Next, regarding the second solution, casting is not pretty. It feels silly - if my variable is of type Ferrari, shouldn't Java be able to implicitly cast it without warning me? After all, Java must know that the returned object can be casted to Ferrari, no?
Is there another workaround? Just out of curiosity - I can live with casting stuff, telling Java what things are supposed to be...
This solution uses generics in a way that is used more often in the Java libraries.
It works and you don't have to cast the result every time nor override the myself method in every subclass.
I believe that it is the only solution that doesn't require overriding or casting. It does require each subclass to use its own type as a type parameter to the superclass Car: class Ferrari extends Car<Ferrari>
class Car<X extends Car<X>> {
public X myself() {
return (X) this;
}
}
class Ferrari extends Car<Ferrari> {
}
And then use it as you intended:
Ferrari testarossa = new Ferrari().myself();
This concept is used in the Java standard libraries a few times as well in one way or another:
java.lang.Enum
public abstract class Enum<E extends Enum<E>>
java.util.Comparable
public interface Comparable<T>
(You're supposed to pass your own class type when you implement a comparable: class ShoeSize implements Comparable<ShoeSize>)
Method chaining
There's a good use for this too - there is a pattern, favored by some, that allows method chaining. This is what StringBuilder does: new StringBuilder().append("a").append("b").toString(). However a class that supports method chaining is often hard to subclass. Using the approach I outlined above makes it possible to subclass in this situation.
This also depends on how you know the foo variable.
If you know it by
Ferrari foo = new Ferrari();
then an overridden method like
class Ferrari extends Car {
#Override
public Ferrari myself() {
return this;
}
}
will allow you to exploit the covaraince, and you can do
Ferrari foo = new Ferrari();
Ferrari bar = foo.myself();
although there are probably not many application cases where this makes sense: When you already know that it is a Ferrari, you could just write
Ferrari bar = foo;
The situation is different when you only know it by
Car foo = new Ferrari();
Then you're out of luck: You don't know the runtime type any more, and you'll have to cast anyhow.
(Note: Such an overridden method returning this with a more specific type has a real application case when it comes to self-referential generic types. This is sometimes referred to as the getThis trick)
Concerning your statement
It feels silly - if my variable is of type Ferrari, shouldn't Java be able to implicitly cast it without warning me? After all, Java must know that the returned object can be casted to Ferrari, no?
This is not true. No one prevents you from overriding the method like
class Ferrari extends Car {
#Override
public Car myself() {
return new Volkswagen();
}
}
and then the cast would no longer be valid
A sub-class may override a base-classes method, and as part of that contract indicate that it will return the specific type. This provides clarity to the user of the class, whereas expecting the user to know the type being returned and cast it accordingly does not. Therefore, overriding is better.

<T extends AnInterface> vs <? extends AnInterface>

I am a little confused with something.
I have a class where its not a collection, but it does refer to generic objects:
public class XClass<E extends AnInterface>{
E instanceobject;
public void add(E toAdd){}
}
public interface AnInterface{}
public class A implements AnInterface{}
public class B implements AnInterface{}
I believe I read somewhere that <? extends AnInterface> is to be used (when declaring an instance of XClass) if you want multiple subtype-types in the generic object at the same time, whereas <T extends AnInterface> would only allow you to have a single type of subtype in the generic class at once?
However, I can just use:
XClass<AnInterface> xc = new XClass<AnInterface>();
A a = new A();
B b = new B();
xc.add(a);
xc.add(b);
and this way I can pass in multiple subtypes of Supertype to the generic class......
I am not seeing the purpose of using "?" and is there anything wrong with using the Interface as the generic parameter?
The reason why you can add objects of both type A and B is due to the fact that you parametized your XClass with the interface, so there is nothing wrong with adding two different classes that implement that interface.
If, on the other hand, you had defined XClass as:
XClass<A> xc = new XClass<A>();
then the expression xc.add(b); would give a compilation error, since all the objects added must have the same type as was declared, in this case, A.
If you declare you xc as, for instance:
XClass<? extends AnInterface> xc = new XClass<AnInterface>();
Then it's not legal anymore to add a or b, since the only thing we know is that xc is of some unknown but fixed subtype of AnInterface, and there is no way to know if that unknown type is A or B or anything else.
But let's say you're writing a method to accept a XClass type that you can iterate over the elements that were added before. Your only restriction (for the sake of the example), is that the items extend AnInterface, you don't care what the actual type is.
You can declare this method like:
public static void dummyMethod(XClass<? extends AnInterface> dummy){
//do stuff here, all the elements extend (implement in this case), AnInterface, go wild.
}
And now you can pass into this method anything like XClass<A>, XClass<B> or XClass<AnInterface>, and it will all be valid.
Keep in mind that you can't add to the object you pass, for the same reason above. We don't know what the unknown type is!
public static void dummyMethod(XClass<? extends AnInterface> dummy){
//do stuff here, all the elements extend (implement in this case), AnInterface, go wild.
dummy.add(new A()); //you can't do this, we have no idea what type ? stand for in this case
}
You can use E if you want to have an instance of XClass to use only one subclass of AnInterface and no other Classes implementing AnInterface that do not extend / implement E.
For example given
public class ClassOne implements AnInterface {} and public class ClassTwo implements AnInterface {}
If you were to use
public class XClass<E extends AnInterface> and <ClassOne>XClass xc = new <ClassOne>XClass() then you can only use an object of ClassOne in your add method not one of ClassTwo. Using ? would allow you to pass in any class implementing AnInterface, either ClassOne or ClassTwo.
Using Identifier E means "For this object I want to use type E and any subclasses", using ? means "I want to use any type that matches the the expression"
In your example you need type erasure in the method "add", so you should't use wildcards in your class.
Wildcards are only to be used when you do not need type erasure (i.e. you don't care about the type as long as it is a subclass of..) and also when you will need to subtype the generics itself.
The wildcard simply means that it will be some class that meets that criteria. So ? extends AnInterface means it will be one (and only one) class that extends AnInterface.
So it could be:
XClass<Impl1>
XClass<Impl2>
etc...
However, at runtime, you don't know what that class will be. For this reason calling methods which take the actual type as a parameter is inherently unsafe, since it's impossible for the compiler to know if the parameter is appropriate for the actual instantiated instance.
Take lists as an example. Something might be declared like this:
List<? extends Number> list = new ArrayList<Integer>();
What would happen if you try to do either of these:
list.add(new Double(0));
list.add((Number) new Long(1L));
It would not compile, because the generic parameter type is unknown at compile time. So the compiler can't tell if Double or Number would be appropriate to pass to the actual instance (in this case ArrayList<Integer>). This is when you get the infamous capture-of compile error.
This, however is permissible, since you know for certain at compile time that the list can take any instance of Number (which includes subclasses).
List<Number> list = new ArrayList<Number>();
list.add(new Double(0));
list.add((Number) new Long(1L));

Custom Generics explanation

Please explain the custom 'T' in the java interface. It is using generics here and of type 'T' i suppose. Then where is the type 'T' defined?
public interface TemplateBuilder<T extends TemplateBuilder>
T is not an actual class. It is determined at compile time depending on the usage of your class TemplateBuilder. Just think of it as a place holder for various possible types, one of which is 'chosen' depending on your circumstances.
For a simpler example, look at the following (adapted from Java's tutorial):
Imagine you want to declare a class Box, which can take a specific type (of the object to hold inside the box), but you wish to reuse this in various circumstances to hold various different types.
So instead of fixing the actual type the Box can take, you declare it as follows:
public class Box<T> {
private T t; // T stands for "Type"
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
When you use it, you then do something like:
Box<Integer> integerBox = new Box<Integer>();
Whats the whole point you might ask? Why not make Box take an Object?
In fact before Java 1.5 this was not possible. This was introduced to have further type-safety in these situations, and was adopted in the Collections framework.
The whole point is that without this mechanism, if instead it used Object, you can't force a specific instance of your Box to hold only Integers. On the other hand, if you made it use specifically Integers, you can't reuse your Box for String, or other objects, and you would need to create another type of Box class.
Before Java 1.5, objects like ArrayList took plain Objects, however there were often cases of type safety broken at runtime, because the program is assuming a list of Integer objects and by mistake somewhere a String is inserted. Generics (through this magic T) force types without restricting what they might be.
In your case T extends TemplateBuilder is going one step further and stating that whatever T is, it must be a class that extends TemplateBuilder. If that wasn't there, it would be any class that extends Object (the universal base class of Java).
T is any Object that extends from TemplateBuilder
T means any Object. for example
List<T> list = new ArrayList<T>();
here T can be Integer, String ...
and <T extends A> means any Object T extends from A
This type is defined when implementing the interface, i.e.
class StringBuilder implements TemplateBuilder<StringBuilder> {}
BTW, see class Enum (the base class of all enums).
My Custom Generics Explanation
Backgorund:
Custom generics are used invariably with data structures e.g. when managing(storing/retrieving) lists of "things"
You do not need to do your own type checking in order for the code to compile as custom generics incorporates the principles of polymorphism.
However, in contrast to the "traditional" OO principles of polymorphism, a class can store a list of things without having any relationship with the "thing(s)" it is storing (The Fundamental Principle of OO where A is a super class of B class is not required)
You do not make separate subclasses for every possible kind of class of "things" you wish to store.
Example 1
As an example consider the following two classes below which are unrelated. This is a very primitive example but nonetheless gives an outline of the principles of custom generics:
/**
*
* Class A is a Custom Generic class that can be 'typed'
* to any kind of class using diamond 'T' syntax.
*
*/
class A<T>
{
// The instance variable of the object type 'T' known at run time
T theI;
// The constructor passing the object type 'T'
A(T anI)
{
this.theI = anI;
}
// Method to return the object 'T'
T getT()
{
return theI;
}
}
Below is the class B which is unrelated to class A i.e. B does not extend A:
/**
*
* Simple class which overrides the toString()
* method from Object's class toString() method
*
*/
class B
{
#Override
public String toString()
{
return "B Object";
}
public static void main(String[] args)
{
A<B> a = new A<>(new B());
System.out.println(a.getT());
}
}
In Main method of class B above:
a.getT() returns the object 'T' which in this example is of type 'B' (This is an example of polymorphism).
a.getT() returns the object 'T', object instance C's method toString() gets IMPLICITLY called, as it is overriding Object's toString() method and prints "B Object".
The interesting aspect to note about Custom Generics and polymorphism is that:
In the context of custom generics, there are no constraints for a relationship among classes in order to execute polymorphism
e.g. Class B is unrelated to A above i.e class B DOES not extend A.
In "traditional" object orientated polymorphism principles, there is invariably a requirement constraint for classes to be related in some way. However, this is not required in custom generics.
Example 2
public interface TemplateBuilder<T extends TemplateBuilder>
The above means that TemplateBuilder interface can be typed to any class that extends TemplateBuilder.
Let's assume SomeClass extends TemplateBuilder then the following is fine:
TemplateBuilder<SomeClass> tbRef = ...
/* Using an Anonymous Inner Class reference to interface TemplateBuilder<SomeClass> */
or
TemplateBuilder<SomeClass> tbRef = .... /* Referencing a concrete class
that implements TemplateBuilder */

Why in java enum is declared as Enum<E extends Enum<E>> [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
java Enum definition
Better formulated question, that is not considered a duplicate:
What would be different in Java if Enum declaration didn't have the recursive part
if language designers were to use simply Enum<E extends Enum> how would that affect the language?
The only difference now would be that someone coud write
A extends Enum<B>
but since it is not allowed in java to extend enums that would be still illegal.
I was also thinking about someone supplying jvm a bytecode that defines smth as extending an enum - but generics can't affect that as they all are erased.
So what is the whole point of such declaration?
Thank you!
Edit
for simplicity let's look at an example:
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
what's wrong with this class structure? What can be done that "MyEnum<E extends MyEnum<E>>" would restrict?
This is a common question, and understandably so. Have a look at this part of the generics FAQ for the answer (and actually, read as much of the whole document as you feel comfortable with, it's rather well done and informative).
The short answer is that it forces the class to be parameterized on itself; this is required for superclasses to define methods, using the generic parameter, that work transparently ("natively", if you will) with their subclasses.
Edit: As a (non-)example for instance, consider the clone() method on Object. Currently, it's defined to return a value of type Object. Thanks to covariant return types, specific subclasses can (and often do) define that they return a more specific class, but this cannot be enforced and hence cannot be inferred for an arbitrary class.
Now, if Object were defined like Enum, i.e. Object<T extends Object<T>> then you'd have to define all classes as something like public class MyFoo<MyFoo>. Consequently, clone() could be declared to return a type of T and you can ensure at compile time that the returned value is always exactly the same class as the object itself (not even subclasses would match the parameters).
Now in this case, Object isn't parameterized like this because it would be extremely annoying to have this baggage on all classes when 99% of them aren't going to utilise it at all. But for some class hierarchies it can be very useful - I've used a similar technique myself before with types of abstract, recursive expression parsers with several implementations. This construct made it possible to write code that was "obvious" without having to cast everywhere, or copy-and-paste just to change concrete class definitions.
Edit 2 (To actually answer your question!):
If Enum was defined as Enum<E extends Enum>, then as you rightly say, someone could define a class as A extends Enum<B>. This defeats the point of the generic construct, which is to ensure that the generic parameter is always the exact type of the class in question. Giving a concrete example, Enum declares its compareTo method as
public final int compareTo(E o)
In this case, since you defined A to extend Enum<B>, instances of A could only be compared against instances of B (whatever B is), which is almost certainly not very useful. With the additional construct, you know that any class that extends Enum is comparable only against itself. And hence you can provide method implementations in the superclass that remain useful, and specific, in all subclasses.
(Without this recursive generics trick, the only other option would be to define compareTo as public final int compareTo(Enum o). This is not really the same thing, as then one could compare a java.math.RoundingMode against a java.lang.Thread.State without the compiler complaining, which again isn't very useful.)
OK, let's get away from Enum itself as we appear to be getting hung up on it. Instead, here is an abstract class:
public abstract class Manipulator<T extends Manipulator<T>>
{
/**
* This method actually does the work, whatever that is
*/
public abstract void manipulate(DomainObject o);
/**
* This creates a child that can be used for divide and conquer-y stuff
*/
public T createChild()
{
// Some really useful implementation here based on
// state contained in this class
}
}
We are going to have several concrete implementations of this - SaveToDatabaseManipulator, SpellCheckingManipulator, whatever. Additionally we also want to let people define their own, as this is a super-useful class. ;-)
Now - you will notice that we're using the recursive generic definition, and then returning T from the createChild method. This means that:
1) We know and the compiler knows that if I call:
SpellCheckingManipulator obj = ...; // We have a reference somehow
return obj.createChild();
then the returned value is definitely a SpellCheckingManipulator, even though it's using the definition from the superclass. The recursive generics here allow the compiler to know what is obvious to us, so you don't have to keep casting the return values (like you often have to do with clone(), for example).
2) Notice that I didn't declare the method final, since perhaps some specific subclasses will want to override it with a more suitable version for themselves. The generics definition means that regardless of who create a new class or how it is defined, we can still assert that the return from e.g. BrandNewSloppilyCodedManipulator.createChild() will still be an instance of BrandNewSloppilyCodedManipulator. If a careless developer tries to define it to return just Manipulator, the compiler won't let them. And if they try to define the class as BrandNewSloppilyCodedManipulator<SpellCheckingManipulator>, it won't let them either.
Basically, the conclusion is that this trick is useful when you want to provide some functionality in a superclass that somehow gets more specific in subclasses. By declaring the superclass like this, you are locking down the generic parameter for any subclasses to be the subclass itself. This is why you can write a generic compareTo or createChild method in the superclass and prevent it from becoming overly vague when you're dealing with specific subclasses.

Categories

Resources