Java Generic Type extend multiple classes - java

How can the type for a generic class extend multiple classes? For example, say I have I generic that I want to be able to take objects that are subclasses of Melons or Berries, but not objects that are subclasses of other subclasses of Fruits?
I was thinking something like
public class MyGeneric<T extends Melons & Berries>
but this does not work as an interface is expected after the ampersand, not a class. Additionally, online I saw the suggestion to make an interface and have T implement the interface, however I do not understand how to make an interface that specifies classes that can be accepted by a generic.

& means and. T extends Melons & Berries means that T must be some type that extends both. You evidently want it to mean or. It doesn't. And <T extends Melons | Berries> is not legal java syntax. For good reason - that would be useless.
You may think: Wait, you can't extend 2 things. Yes, you can - extends in generics refers solely to supertypes; it's like a combination of extends and implements.
For example:
void test(List<? extends Serializable & CharSequence> items) {
}
can be invoked by passing a List<String>. That's because String is a subtype of Serializable, and also a subtype of CharSequence.
The 'point' of this is that when you get an element from this list, you can treat it as either. Because it's and - it's a list of both.
There is no way in java to say: "I want to accept a list of Berries, or a list of melons, but not a list of Apples". The reason there's no way to say that, is because its useless:
If there's a thing you can do to both melons and berries but not bananas, then whatever it is will have to be defined in an interface of sorts. Perhaps Melons and Berries both implement 'SeededFruit', and Banana doesn't. In that case, just write List<? extends SeededFruit> isntead.
If you just want to use aspects of melons and berries that are shared by all fruit (also bananas), just write List<? extends Fruit> - why put up arbitrary restrictions?
If you want to write if (x instanceof Melons) doThing1; else if (x instanceof Berries) doThing2; - java isn't 'meant' for that. There are tons of things java doesn't have that would be really convenient if everybody wrote code like that. But java doesn't have that, will not have that, folks don't usually write their java code like that. Usually if someone does, they're writing very 'bad' code, in the sense that it is overcomplicated and/or hard to maintain and/or hard to adopt in the face of changing requirements, and needlessly so: You could write it differently and avoid those traps.

The way I would do is to group the classes using an interface. Then I use the interface to define the generic class. See below:
interface ForGenerics { }
class Fruit { }
class Melon extends Fruit implements ForGenerics {}
class Berry extends Fruit implements ForGenerics {}
class Apple extends Fruit {}
class MyGeneric<T extends ForGenerics> { }
public class Main{
public static void main(String[] args) {
MyGeneric<Melon> a;
MyGeneric<Berry> b;
// can't make MyGeneric of Apple
// MyGeneric<Apple> c;
}
}

Related

How to prohibit a subclass from having a method?

In my Java project, I have the method addType1AndType2() which has windows where you expand lists and select objects from the list. It was very complicated and time consuming to create, as things must be scrolled and xpaths keep changing. There are two lists in this which are actual names but, due to company proprietary info, I will just call them Tyep1 and Type2.
Now I have an UpdateType1 class which uses all the complicated methodology in the AddType1AndType2 but has nothing related to Type2 in it. I could copy the AddType1AndType2 and cut everything I do not need, but that would be replicating and changes would have to be duplicated in both classes. This defeats the purpose of inheritance and reusability.
I can make a class UpdateType1 extends AddType1AndType2{} which I have done. But there are still methods like selectType2Value() which are inherited but not possible in the subclass.
If I do an #Override and declare the class as private in the sub class, I get an error that I cannot reduce the visibility in a subclass.
Any idea what I can do? Right now I am just putting a throw new AssertError("Do not use") but that seems kind of lame. Is there a better thing to do that would even give a compile-time error rather than an assert at run time, or is this the best way?
The thing is: your model is wrong.
Inheritance is more than just putting "A extends B" in your source code. A extends B means: A "is a" B.
Whenever you use a B object, you should be able to put an A object instead (called Liskov substitution principle).
Long story short: if B has methods that A should not have ... then you should not have A extends B.
So the real answer is: you should step back and carefully decide which methods you really want to share. You put those on your base class. Anything else has to go. You might probably define additional interfaces, and more base classes, like
class EnhancedBase extends Base implements AdditionalStuff {
Edit: given your comment; the best way would be:
Create interfaces that denote the various groups of methods that should go together
Instead of extending that base class, use composition: create a new class A that uses some B object in order to implement one/more of those new interfaces.
And remember this as an good example why LSP really makes sense ;-)
Create the interfaces
public interface IAddType1 {... /* methods signtatures to add Type1 */}
public interface IAddType2 {... /* methods signtatures to add Type2 */}
public interface IUpdateType1 {... /* methods signtatures to update Type1 */}
then your current code at AddType1AndType2 will become just a base helper class:
public abstract class BaseOperationsType1AndType2{
//code originally at AddType1AndType2: methods that add Type1 and Type2
}
then your new AddType1AndType2 class will be:
public class AddType1AndType2
extends BaseOperationsType1AndType2,
implements IAddType1 , IAddType2 {
//nothing special.
}
and your new UpdateType1can be defined as
public class UpdateType1
extends BaseOperationsType1AndType2
implements IUpdateType1 {
//
}
Voila.
You can use 'final' keyword to prohibit extending a method in a subclass.
A method with a 'final' modifier cannot be overriden in a subclass.

Understanding java recursive generic type definitions with type erasion

I'm very confused facing this line of code:
public abstract class ClassName<T extends ClassName<?>>{}
I know what <T> is, what abstract is, what inheritance is but I just can't summarize all I see in this line.
Please can someone explain in simple words what does that interesting thing means?
Not a duplicate of questions about <T> and <?>. The confusing thing here is that ClasName appears twice.
Thanks in advance.
public means the class is visible to all other classes.
abstract means the class can not be instantiated (you'll have to find a non-abstract subclass for that)
inheritance is an important concept in object-oriented programming. Read a book about OOP or consult wikipedia.
T extends ClassName<?> means there is an upper bound put on the type parameter T, such that T needs to be a subclass of ClassName<?>. ? means unbounded type parameter.
I will provide a little more meaningful example that might make it easier to understand the concept of using bounded recursive type parameters. Lets assume you have a class Thingy. You want all subclasses of Thingy to be comparable, but just to the same subclass. Ie you want nails to be comparable to nails, but not bikes:
interface Thingy<T extends Thingy<T>> extends Comparable<T> {}
class Nail implements Thingy<Nail> {
#Override public int compareTo(Nail o) { ... }
}
class Bike implements Thingy<Bike> {
#Override public int compareTo(Bike o) { ... }
}
So ClassName has a generic parameter T and this parameter needs to fit a certain requirement, in this case extends a certain type S, that means, T must inherit S. Now the interesting thing in this case is this S.
We have S to be ClassName<?>, so T must inherit from ClassName with a wildcard. For the wildcard aka the question mark please have a look at the link Michael Markidis gave in a comment to your question.
The real fun now is that this definition
public abstract class ClassName<T extends ClassName<?>>
allows recursive generic type defintion. So you could have something like
ClassName<ClassName<ClassName<ClassName<?>>>> test;
for whatever that's worth :)
EDIT: Given
ClassName2<T extends ClassName<?>> extends ClassName<T>
thats relatively easy in comparison. We want to inherit ClassName but not "destroy" the generic argument, so we take one ClassName would accept, in this case T extends ClassName<?>. In extends ClassName<T> the compiler checks if this (i.e. ClassName2's) T fits the T of ClassName, which was the requirement (remember ClassName's definition) T extends ClassName<?>, so this obviously works.
In addition, we have ClassName2<?> extending ClassName<?>, so now you can mix the two types however you want:
ClassName2<ClassName<ClassName<ClassName<?>>>> test2;
ClassName2<ClassName<ClassName2<ClassName<?>>>> test3;
However, if you would have, say
class ClassName3<T extends ClassName3<?>> extends ClassName<T>
(the public and abstrac modifiers don't really influence the generic behavior here), you can only have things like
ClassName3<ClassName3<ClassName3<ClassName3<?>>>> test4;
ClassName2<ClassName<ClassName3<ClassName3<?>>>> test5;
since ClassName and ClassName2don't inherit ClassName3.

Java: Generics on data structures and wildcards

I'm trying to learn how to use generics and for that, I'm creating my own data structure similar to a list with an Iterator and all.
The uppermost class is declared as:
public class BasicList<A> implements Iterable {
}
It's just a list with nodes and a single pointer to the next element.
There's another list, called DescendingList, that does pretty much the same, only this time around, you're getting another output since the Iterator is different. I'm giving a comparator to this List to get the Iterator to work. The comparator is just an interface:
public interface Bigger<A> {
boolean bigger(A x);
}
DescendingList looks like this:
public class DescendingList<A extends Bigger<A>> extends BasicList<A> implements Iterable {
}
The idea is that it could work with any kind of object that is comparable through the Bigger interface.
Now I have an abstract class:
public abstract class Rock implements Bigger<Rock> {
}
And finally, a normal class which extends the Rock class:
public class Mineral extends Rock {
}
So, the issue at hand is that, while I can easily create a new BasicList filled with Minerals like this:
BasicList<Mineral> min = new BasicList<Mineral>();
I can't do the same with the DescendingList. Whenever I try going with
DescendingList<Mineral> min = new DescendingList<Mineral>();
my IDE (IntelliJ) goes all
"Type parameter "Rock" is not within it's bound; should implement Bigger<Mineral>"
And I don't really get why that happens. I am pretty sure that I've messed up the type parameters somehow and I'm really not sure where. This should be solveable somehow (at least without removing any classes/interfaces - the class headers might be and probably are completely messed up). Thanks in advance for any help you might offer.
A Mineral isn't a Bigger<Mineral>, it's a Bigger<Rock>, and that is incompatible with Bigger<Mineral>, because even though a Mineral is a Rock, Java's generics are invariant. It needs to be a Bigger<Rock> because of how Rock is defined -- implementing Bigger<Rock> -- and that DescendingList declares type parameter A to be a Bigger<A>.
Because it's a consumer (type parameter as a method parameter), the type parameter A needs a lower-bound (super) on its declaration.
class DescendingList<A extends Bigger<? super A>> // ...
This way Mineral will be within its own bound.
As an aside, you are implementing the raw form of Iterable in BasicList; you should supply a type argument there.

java generics, how to extend from two classes?

I want to have a Class object, but I want to force whatever class it represents to extend class A and also class B.
I can do
<T extends ClassA & ClassB>
but it is not possible to extend from both classes, Is there a way to do this?
In java you cannot have a class which extends from two classes, since it doesn't support multiple inheritance. What you can have, is something like so:
public class A
...
public class B extends A
...
public class C extends B
...
In your generic signature, you can then specify that T must extend C: <T extends C>.
You could give a look at Default Methods (if you are working with Java 8), which essentially are methods declared within interfaces, and in Java, a class can implement multiple interfaces.
A simple way for this problem is inheritance.
public class A { // some codes }
public class B extends A { }
<T extends A>
Java does not have multiple inheritance as a design decision, but you may implement multiple interfaces.
As of Java 8 these interfaces may have implementations.
To use multiple classes there are other patterns:
If the parent classes are purely intended for that child class, but handle entirely different aspects, and were therefore separated, place them in a single artificial hierarchy. I admit to doing this once.
Use delegation; duplicate the API and delegate.
Use a lookup/discovery mechanism for very dynamic behaviour.
public T lookup(Class klazz);
This would need an API change, but uncouples classes, and is dynamic.

How do I create a subclass of a generic class with more restrictive types?

This class is intended to represent a pair of objects of arbitrary types - what a python dev might think of as a 2-tuple.
public class Pair<DD extends Comparable<DD>,VV> implements Comparable< Pair<DD,VV> > {
DD d;
VV v;
// Implementation removed.
}
I want to make a new subclass called NumberPair - the only difference is that while Pair can conceivably contain any two classes of object, my NumberPair class will only be allowed to contain numbers.
Can anybody tell me how to express this?
PS. Admittedly this looks like a silly design given that anywhere we might use this class we could also use a Map - please ignore that for now.
I'm not sure if I completely get the problem, but I think this might be what you're looking for:
public class NumberPair<NDD extends Number & Comparable<NDD>, NVV extends Number> extends Pair<NDD, NVV> {}
This forces both type parameters to extend Number.
This is declaration:
public class NumberPair<VV> extends Pair<Number,VV> {
}

Categories

Resources