I know in Java Generics, there is T extends something, but I want T implements something.
Is there any way to achieve this other than using the explicit cast?
For instance, I want to make sure everything passed to sorting algorithm implements Comparable. Implements, not extends.
Thank you.
For generic type bounds, extends isn't limited to classes; you can also use it for interfaces. For example, <T extends Runnable> is OK.
Related
I am writing some classes using Generics but I can't find a solution
for the class SolutionsSubset and so I a getting the error
"type parameter S is not within its bound". I have read previous
questions about the same error but I can't solve it for my case.
Could anybody help me to improve my knowledge about generics? Any
reference to a good book (I can find in google a lot of information
but if someone can reccommend a book, tutorial, etc. will be welcome).
Although I tried to keep in mind the rules to ask a question but I
apologize if my question doesn't fulfill these rules.
I have the following classes and interfaces:
public interface Subset<T extends Comparable<T>> extends Comparable<Subset<T>>
public class MathSubset<T extends Comparable<T>> extends TreeSet<T> implements Subset<T>
public interface Solution<T extends Comparable<T>>
public interface Solutions<S extends Solution<?>> extends Iterable<S>
public class SolutionsSubset<S extends Solution<?>> extends MathSubset<S> implements Solutions<S>
I need that Subset extends Comparable. In SolutionsSubset, the class MathSubset stores Solution objects. How do I have to change these definition to make it work?
Thanks you in advance
In order to be used as the type argument in MathSubset, SolutionsSubsets S must extend Comparable<S>. As a compilable example:
import java.util.TreeSet;
interface Subset<T extends Comparable<T>>
extends Comparable<Subset<T>> { }
class MathSubset<T extends Comparable<T>>
extends TreeSet<T>
implements Subset<T>
{
public int compareTo(Subset<T> other) { throw new Error(); }
}
interface Solution<T extends Comparable<T>> { }
interface Solutions<S extends Solution<?>> extends Iterable<S> { }
class SolutionsSubset<S extends Solution<?> & Comparable<S>>
extends MathSubset<S>
implements Solutions<S>
{ }
A few comments: This is very abstract example, and so not easy to think about. Laying out the code so you don't need to scroll is good. There's an awful lot of inheritance going on here, perhaps compose rather than, say, extending TreeSet. It's difficult to distinguish between the identifiers Solutions and Solution.
Generics are something that can quickly get out of hand, especially if you try to "be all generic" all at once. Less is more. What always helps me is to start concrete (including the implementation) and then slowly substitute generic parameters in, one parameter and class at a time.
Could anybody help me to improve my knowledge about generics?
http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Not a tutorial, but lots of useful info. Its one of those references that you read the parts you can understand, but come back to over and over again in the future as you gain more mastery and more of it begins to make sense.
First of all, here is the full error (which is specific to MathSubset not getting a proper parameter): Bound mismatch: The type S is not a valid substitute for the bounded parameter <T extends Comparable<T>> of the type QifFixer.MathSubset<T>
The problem is that MathSubset expects a <T extends Comparable<T>, but you're giving it a S extends Solution<?> - those types having nothing to do with each other, because a Solution does not inherit or implement Comparable<T>.
If anything, you could try this:
public class SolutionsSubset<S extends Comparable<S>> extends
MathSubset<S> implements Solutions<Solution<S>>;
Unfortunately, this will STILL not work because MathSubset implements Iterable, but so does Solutions.
An easy fix would be for Solutions to not extend Iterable, but it really sounds to me like you're trying to use a more complex approach than you need to. May be a "has-a" instead of "is-a" design might be more beneficial here?
I'm trying to make a map of objects that both implement and extend. The class they are extending (JPanels) I have no control over. I do, however, have control over the interface.
This is what I've tried
Map<MyEnum, ? extends JPanel & MyInterface> myMap;
That, however, is a compile time error.
I could make an abstract class and then make the subclasses extend it, but that seems a bit heavy handed (or is it?).
For the record, I'm using Java 6
That, however, is a compile time error.
Yes. You can't give multiple bounds to wildcards. There is some restriction on where you can use wildcards, and where you can use type parameters. Type parameters can have multiple bounds, but they can't have lower bounds. Wildcards on the other hand, can have lower bounds, but they don't have multiple bounds.
One option is to have the type parameter declared as a part of your class, and give multiple bounds to it:
class MyClass<T extends JPanel & MyInterface> {
Map<MyEnum, T> myMap; // This would work fine now
}
See also:
What is difference between <? extends Object> and <E extends Object>?
References:
Angelika Langer's - Java Generics FAQs
What is a type parameter bound?
What is the difference between a wildcard bound and a type parameter bound?
I could make an abstract class and then make the subclasses extend it, but that seems a bit heavy handed (or is it?).
Not at all: this should work just fine.
Another approach is to add an interface that combines the methods of JPanel of interest to your methods that use myMap, and use it like this:
interface MyPanelInterface extends MyInterface {
void updateUI();
}
...
class MySpecialPanel extends JPanel implements MyPanelInterface {
...
// Implementation for updateUI() comes from JPanel
// You are responsible for implementing the remaining methods.
}
...
Map<MyEnum, ? extends MyPanelInterface> myMap;
...
myMap.get(MyEnum.FIRST).updateUI();
You should create your own class that extends the JPanel and implements MyInterface as you too suggested, then use Map<? extends MyNewSuperClass> myMap;
I never had to do this, but as you suggested you may go ahead and create a new class or interface (based on your need) implementing/extending the interfaces/classes you need and then use it in your Map.
Public Interface IWhatIneed implements Jpanel, MyInterface{
...
}
and then:
Map<MyEnum, ? extends JPanel & MyInterface> myMap;
I hope this would help
I need to parameterise my class by Enum with some concrete methods, something like:
class K<E extends Enum<E> implements SomeInterface>
But Eclipse prohibit me to use "implements" word in "<>". What can I do to solve my problem? Is there any sensible reason why can't I use "implements" in definition of generic type?
Generic constraints use the word extends for both base classes and interfaces.
To constrain on multiple types, use an &:
class K<E extends Enum<E> & SomeInterface>
You would use extends in this case:
class K<E extends Enum<E>&SomeInterface>
Please note that if it needs to also extend a class it must come before any interfaces.
Compiles:
public class SerializableObject<T> implements Serializable
{
public T m_object;
}
Does NOT compile:
public class SerializableObject<T> extends T implements Serializable
{
}
So, I want a generic class to derive from its generic type parameter.
Why?
Let's say I have a Map<K, V> and I simply want to serialize it.
I also don't know ahead which keys I'll have.
How do I do that?
So, I want a generic class to derive from its generic type parameter.
You just can't do that, I'm afraid. There are various technical reasons for this, not least of which is type erasure.
You should look for an alternative solution to your issues - this idea is a dead end.
Nope, your goal is near a Dynamic type, which java does not support.
I'm upgrading some code to Java 5 and am clearly not understanding something with Generics. I have other classes which implement Comparable once, which I've been able to implement. But now I've got a class which, due to inheritance, ends up trying to implement Comparable for 2 types. Here's my situation:
I've got the following classes/interfaces:
interface Foo extends Comparable<Foo>
interface Bar extends Comparable<Bar>
abstract class BarDescription implements Bar
class FooBar extends BarDescription implements Foo
With this, I get the error 'interface Comparable cannot be implemented more than once with different arguments...'
Why can't I have a compareTo(Foo foo) implemented in FooBar, and also a compareTo(Bar) implemented in BarDescription? Isn't this simply method overloading?
Edit: I have many classes which extend BarDescription. If I remove the type parameter for Comparable on Bar, leaving it in the raw state, then I get a bunch of compiler warnings when sorting all the classes which extend BarDescription. Would this be solved with the wildcards answer below? That answer looks quite complicated and difficult to understand for maintenance.
Generics don't exist after bytecode has been compiled.
Restrictions from this: You can't implement / extend two or more interfaces / classes that would be same without the generic parameter and are different with the generic parameter.
What you could do if you really really want type safety is:
interface Foo<T extends Foo<?>> extends Comparable<T>
interface Bar<T extends Bar<?>> extends Comparable<T>
abstract class BarDescription<T extends Bar<?>> implements Bar<T>
class FooBar extends BarDescription<FooBar> implements Foo<FooBar>
I'd write a couple of Comparators and be done with it.
Having multiple implementations of generic interfaces would run into problems when you consider wildcards.
This does not depend upon erasure.