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?
Related
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.
I just stumbled with a situation I think I have not tried before.
I have this:
class A<DATA>
class B extends A<SomeSpecificDataClass>
Now, I want to declare a third class like this:
class C <T extends A<DATA>{
public someMethod(T instance, DATA data){}
}
I know I could just ask the instance for its data, but for the API I'm building, I'd REALLY prefer to have a syntax like this. Any ideas how to do it?
Thanks in advance.
Since DATA would be another generic, then you should declare that the class uses two generics:
class C<DATA, T> {
}
Then, you could define other requirements for T based on DATA:
class C<DATA, T extends A<DATA>> {
}
Is there is any actual difference between these this generic
public class SelfBounded <T extends SelfBounded<T>>{}
and this one
public class SelfBounded <T extends SelfBounded>{}
?
If yes, then how can I observe them?
There are a lot of similar questions here already.
You can read the following article
Or the following questions:
Java Enum definition
Why in java enum is declared as Enum<E extends Enum<E>>
What would be different in Java if Enum declaration didn't have the recursive part
The second one uses a raw type, which should never be used.
But actually neither of these declarations are normally useful. You should almost certainly just use
public class SelfBounded <T>
I'd like to implement the following classes with the following hierarchy:
public class DwellingPropertySetter
extends AbstractPropertySetter<Dwelling>
public class HousePropertySetter
extends DwellingPropertySetter<House>
public class SkyscrapperPropertySetter
extends HousePropertySetter<Skyscrapper>
Unfortunately this code won't compile. A way to do it would be this:
public class DwellingPropertySetter<T extends Dwelling>
extends AbstractPropertySetter<T>
public class HousePropertySetter<T extends House>
extends DwellingPropertySetter<T>
public class SkyscrapperPropertySetter<T extends Skyscrapper>
extends HousePropertySetter<T>
But for me those extends keywords are unnecessary.
Whenever I want to use a SkyscrapperPropertySetter I'd have to specify a type parameter. This is useless and would then look like SkyscrapperPropertySetter<Skyscraper>.
Do you know a way out for me? The only other way I know to realise my first hierarchy would be using interfaces and delegate methods.
I think you have correctly recognized it is pointless to have something like ChickenArrayList<Chicken>, so you can either create something like
class ChickenArrayList extends ArrayList<Chicken>
OR, if you want to reuse some functionality in ChickenArrayList, you may have to make it abstract (and generic) and put another concrete, non-generic class on top of it:
class AbsChickenArrayList<T extends Chicken> extends ArrayList<T>
// and
class ChickenArrayList extends AbsChickenArrayList<Chicken>
class HenArrayList extends AbsChickenArrayList<Hen>
I know this is quite verbose, but this is the best you can do with this ~18 year old language.
I think you can achieve what is reasonable. If you have
public class DwellingPropertySetter
extends AbstractPropertySetter<Dwelling>
That means you have already made DwellingPropertySetter non-generic, all the method signatures will use Dwelling. If you say
public class DwellingPropertySetter<T extends Dwelling>
extends AbstractPropertySetter<T>
that means there can be various DwellingPropertySetters -- and you really would like to have different ones, so I think this is what you really want to keep. Or is it your complaint that you want both a DwellingPropertySetter with no args, where Dwelling is assumed, AND a subclass extending DwellingPropertySetter<T> with a different T? That cannot be had with Java Generics.
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.