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>> {
}
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'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.
Is there a way to inherit from a baseclass by using the generic type paramater?
public class Extra<BASE> extends BASE
So that Extra is the new class having all the methods of BASE, like
Extra<MyType>
Greetings
edit*******
That is disappointing. I'm moving a project from C++ to JAVA.
In C++ this is possible, sadly I used this a lot in this project.
Is there another way to achieve that:
A class has its own userdata-class. It needs the members of its userdata linked with a special functionality, that is given by an other class. The other class is extending the first userdata-class. I don't want to have the userdata as a data member in the new class,
but really as a part of it.
Like:
userdata-class:
String name;
special-functionality-class: a generic TreeKnot,
The new class then should be a TreeKnot combined with the userdata-class.
What way could I go ?
No, it is not possible you can create something like this
public class Extra extends Base<Base>
But what do you want it is not possible at all!!!!
No, it's not possible. Type templating and inheritance are two completely different concepts.
I need to define a generic class, and the type parameter must be an enum. I think it should look something like
public class <T> MyClass<T extends Enum<T>> {
}
But I can't seem to figure out the exact syntax. I should mention that I need a way to refer to the type (within MyClass) that it is instantiated with.
Thanks!
public class MyClass<T extends Enum<T>> { }
While the approved answer looks syntactically correct, what's the scenario for such a declaration? Are you trying to write some class that can operate on any enum-defined type, like java.util.EnumSet or java.util.EnumMap? It's an unusual arrangement, so be sure you really need it in order to meet your requirements.
Does something like this make any sense at all in Java?
class A<T extends B> extends T{
int fun1() {
....
}
}
abstract class B extends X implements C {
}
interface C {
int fun1();
}
I want class B to extend both X and C ideally. But since there is no multiple inheritance in Java, I'm trying to come up with a slicker workaround.
The trick is that the stuff that would be defined in C is defined in Super Class "A" instead. The problem is to get A let me use a generic type after "extends"
Thoughts?
No, you can't make a type extend a class specified as a type parameter
Without knowing what A, B, C or X are, it's very hard to recommend an alternative design pattern I'm afraid.
What you're trying to do is not going to work - Java generics have nothing to do with inheritance. There is no multiple inheritance, you'll have to make your peace with that :-)
You can declare multiple interfaces and use aggregation to "fake" multiple inheritance.
As others have said, generics won't help you with multiple inheritance of implementations.
My workaround for not repeating myself due to multiple inheritance is usually to write the common implementation in a static method in the superclass, and delegate to that from the places where it is needed.
The simplest example would be like this:
class A
{
}
class B extends A
{
}
interface C
{
void foo();
}
class CBase extends A implements C
{
public void foo()
{
sFoo(this);
}
static void sFoo(C c)
{
// Implement foo here
}
}
class D extends B implements C
{
public void foo()
{
CBase.sFoo(this);
}
}
Note that to make this useful there would be more operations inherited by D from B and A, which are not shown in this example.
The type parameter is only a placeholder for the compile-time-only generics, it is an actual type.
Trying to come up with a workaround solution for multiple inheritance in a language that does not support it is probably a good indicator that the flaw is in the design. Saying A<T extends B> extends T will obviously fail as it doesn't even mean what you're hoping it to mean - <T extends B> means only that T is of a type that is a B. Appending extends T does not mean anything because T is not defined in that class. Again, this is a compile-time type - the actual type of T is not directly available during runtime.
Are you really sure that what is most properly achieved via multiple inheritance as opposed to composition? It could also be possible that you're trying to get A to do too many things.
A more concrete example might allow others to give more feedback on the design itself.