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.
Related
I have the following three classes:
public class MyClassA extends FooA<Bar>
public class MyClassB extends FooB<Bar>
public class MyClassC extends FooC<Bar>
The classes FooA, FooB and FooC all extend Foobar<V> (-> public class Foobar<V extends FooY> implements IFoobar<V>) but at different inheritance levels. Furthermore, it is worth mentioning that FooA, FooB and FooC are part of an API, which I am not able to modify. In my classes MyClassA, MyClassB and MyClassC, I am using some properties and methods in the exact same way and as a consequence I want to create a parent class which implements this same behavior. However, I am not sure how I can implement this inheritance scenario via generics.
I thought about something like:
public class MyParentClass<V extends Foobar> extends V
And then I would simply do the following:
public class MyClassA extends MyParentClass<FooA<Bar>>
public class MyClassB extends MyParentClass<FooB<Bar>>
public class MyClassC extends MyParentClass<FooC<Bar>>
How can I make this work?
Whenever you are stuck with "too much inheritance", the correct answer might be the old mantra: prefer composition over inheritance.
In other words: keep in mind that inheritance is more than just putting "A extends B" onto some class declaration; and also remember that the primary intention of inheritance is to express a "is a" relationship; it is not meant as a simple way to avoid code duplication. (yes, code duplication is very important, but using inheritance to achieve it is very often a bad idea!)
In that sense: instead of further adding to this "inheritance jungle"; I would rather step back and see if it makes sense to define some new interfaces that better capture the set of functionality that you need; and create classes that implement those interfaces; not based on inheriting other classes, but by instantiating objects of those classes; and putting around some wrapping.
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 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>> {
}
My intention is to set create a class with this type of inheritance:
public class BaseActivity<T> extends <T extends Activity>
but of course this inheritance syntax doesn't compile. Any alternative suggestion where I can arbitrarily select a Tab or Map Activity to be the base of other Activity classes whose override behavior is necessary?
You can't do that, but you can do:
public class BaseActivity<T extends Activity> extends Activity
That's not exactly what I think you mean to express, but perhaps close?
Just a simple syntax question. Suppose we have an interface which we will call IMyClass, and an abstract class that implements which we will call AbstractMyClass and is declared as follows:
public abstract class AbstractMyClass implements IMyClass {
}
Now when we create a concrete implementation of MyClass which we will call... MyClass!, there are two ways in which we can declare it:
public class MyClass extends AbstractMyClass {
}
and
public class MyClass extends AbstractMyClass implements IMyClass {
}
What's best here? I'm supposing the answer to this is just a matter of preference but just wanted to hear some thoughts on this.
Thanks in advance,
Joseph.
The latter form is more explicit about the fact that MyClass is implementing IMyClass intentionally and not by accident. If that's what you intend to stress, this form is more clear. It also guards against future changes to AbstractMyClass. Perhaps at some point it ceases to implement IMyClass.
In most cases the first form is sufficient and extra verbosity buys you nothing.
It is just a matter of preference. FWIW, you can find examples for both in the JDK source:
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
public class ThreadPoolExecutor extends AbstractExecutorService