Generics in Java with and abstract class - java

I was reading some code for learn something about manage data in Android.
When i read a litle of the code...
I find this declaration.
public abstract class DBObject<T extends DBObject<?>> implements Cloneable{}
I understadn that this is and Abstract class with T that is a Generic Object
but i don't understand why y have to put a wildcart after Extend the same class.
Here is all the code
https://github.com/tasks/tasks/blob/master/src/main/java/com/todoroo/andlib/sql/DBObject.java

It looks like this is used so that it can be parameterised with its subclasses. It would be used like so:
class Foo extends DBObject<Foo> { ... }
It appears this is done solely so that the as() method will return the correct type.
The reason for the wildcard is because without it you would have to somehow specify a recursive generic definition, DBObject<T extends DBObject<T extends DBObject<...>>> - which is impossible.
Edit: Although see comments below; the wildcard is not actually necessary.

Related

Get generic parameter of generic parameter during inheritance

Can, and if yes how, I access the generic parameter of another generic parameter, without also specifying it?
The example below is simplified from my current situation. All members and methods are omitted as they aren't relevant to the situation. LibraryRepository is a JPA/Spring-Type expecting an ENTITY and an ID.
abstract class AbstractEntity<ID> {}
class ConcreteEntity extends AbstractEntity<Long> {}
interface AbstractRepository<ENTITY extends AbstractEntity<?????>> extends LibraryRepository<ENTITY, ?????> {}
//Desired declaration:
interface ConcreteRepository extends AbstractRepository<ConcreteEntity> {}
Without specifying Long on AbstractRepository, what to write instead of the two ?????, if that is at all possible?
For the sake of question-scope, please answer the question regarding generics, not how to implement spring-repositories in a better way. I'm glad for hints about that in the comments though.
interface AbstractRepository<ENTITY extends AbstractEntity<?????>> extends LibraryRepository<ENTITY, ?????> {}
One (particularly useful) way of thinking about generics is that they link types together. If you declare a new typevar and use it in only one place, because of erasure, that is effectively useless. Use it in two places and now you've told the compiler that the two places you used your T are linked: They can be anything, as long as they are the same thing.
This way of thinking also provides some insight here: Clearly you want your first ????? to be linked to your second ?????: For them to be equal.
The way to do that, then, is to declare a new typevar and use it:
interface AbstractRepository<ENTITY extends AbstractEntity<Q>, Q>
extends LibraryRepository<ENTITY, Q> {}
Unfortunately, that means AbstractRepository now gained a type variable, and I gather you didn't want that to happen.
Unfortunately, java has no way to link types without a type variable.
As a general rule of thumb, if you mix class hierarchies (things extending things implementing things), and lots of generics, you end up with looooots of generic parameters, and some of those will feel like DRY violations. The solution is to either accept it, or to not do one of those two things (Use composition over inheritance, or reduce the type variables you're using, or move them to methods instead), or to use a bunch of hacky reflection and 'warning-casts' (where you cast things to a typevar, which doesn't actually typecheck anything and tends to result in ClassCastExceptions in bizarre places: Places that don't even have a cast anywhere in the line, and not the place with the faulty code. Resulting in long and arduous bughunting exercises.
Maybe this is what you're trying to avoid, but I think you'd specify the generic parameter of your AbstractEntity as a parameter in AbstractRepository, something like this:
interface LibraryRepository<ENTITY, ID> {}
abstract class AbstractEntity<ID> {}
class ConcreteEntity extends AbstractEntity<Long> {}
interface AbstractRepository<ENTITY extends AbstractEntity<ID>, ID>
extends LibraryRepository<ENTITY, ID> {}
interface ConcreteRepository extends AbstractRepository<ConcreteEntity, Long> {}
I don't know how otherwise the compiler would be able to type-check the generic parameters for LibraryRepository.

How can I restrict arguments of methods in abstract classes for subclasses that use them?

I've been trying to design a set of classes to model a classic RPG. I've found myself confused on how to solve this one issue, however: how do I force the use of character-type (e.g. Tank, Healer, DPS) specific spells/equipment, etc. in an abstract class. The example below better articulates what I mean.
I've got an abstract PlayableCharacter class which all character-types inherit from:
public abstract class PlayableCharacter {
private Set<Spell> mSpells;
...
public void addSpell(Spell spell) {
mSpells.add(spell);
}
}
For example:
public class Healer extends PlayableCharacter { ... }
public class Tank extends PlayableCharacter { ... }
Note the Set of Spell in the abstract class. I would like it if each subclass of PlayableCharacter could use its addSpell method but with the restriction that the type of Spell correspond to the PlayableCharacter subtype.
For example I have these Spell classes:
public abstract class Spell { ... }
public class HealerSpell extends Spell { ... }
public class TankSpell extends Spell { ... }
I only want Healers to use HealerSpells and Tanks to use TankSpells, etc. For example:
PlayableCharacter tank = new Tank();
tank.addSpell(new TankSpell()); // This is fine
tank.addSpell(new HealerSpell()); // I want to prevent this!
I thought of giving each subclass of PlayableCharacter it's own Set of subclass-specific Spells, but that creates a lot of code duplication.
I also tried making PlayableCharacter.addSpell marked as protected, then each subclass would have to implement an interface like this:
public interface Spellable<T extends Spell> { void addClassSpell(T spell); }
and each subclass that implements it would call super.addSpell(spell); but that lead to more code duplication and nothing was forcing those implementations to do the super call.
Is my strategy fundamentally flawed in some way? Any advice? I feel like this issue will keep getting worse as I add more character-type-specific equipment, traits, and so on.
I wouldn't do it that way (via type inheritance). It would be better to add characteristics to a Spell itself because it's a spell, which can be cast by a certain character only. Also, a specific spell can be cast to a certain character type only. These rules belong to a spell, not to a character.
Spell rules can be checked in a runtime by a separate class or by a Spell class itself inside a cast() method or another one.
so far what you have is good
the rest of the stuff, think more strategy pattern than super call
so abstract class can have algorithm that does step1, step2, step3 with possible parent implementation
child classes can override it, but only override parts that is different
when you call algorithm, it performs all steps
Steps themselves could be different class that has logic, if everything becomes too big
maybe have each subclass of playable character store the class (or classes) of subspells that are allowed. then do an if(spell instance of allowedSpell) ...

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.

Is there a way to bound a generic type using an interface in Java?

I am trying to create a generic list which sorts the items entered into it using the .compareTo() method of the type. However, I ran into a problem in the very first line. Since the type must be one which implements Comparable<T>, is there any way to enforce this? I suppose the syntax :
public class GenList<T implements Comparable<T>>{
//Class body.
}
won't work. Any suggestions? Thanks in advance!
I know it's a bit counter-intuitive, but for this you write extends rather than implements:
public class GenList<T extends Comparable<T>>{
//Class body.
}
(Note that I also changed the ? to T, which I think is what you meant. A reference can have type GenList<?>, or type GenList<? extends Comparable<String>>, or whatnot, but it doesn't make sense to declare the class itself as taking a wildcard parameter.)
You mean like
public class GenList<T extends Comparable<T>>{
//Class body.
}

implements vs extends in generics in Java

Can someone tell me what the differences between the first and second codes are?
MaxPQ stands for priority queue, which is a collection of "Key" objects that can be compared with each other.
Code 1:
public class MaxPQ<Key extends Comparable<Key>>{
...
}
Code 2:
public class MaxPQ<Key implements Comparable<Key>>{
...
}
The second code doesn't compile, but it is not intuitive to me why we need to extend instead of implement interfaces when using a generic.
The difference is pretty straightforward: second code snippet does not compile and never will. With generics you always use extends, for both classes and interfaces. Also super keyword can be used there, but it has different semantics.
There is no implements in generics. The second code is invalid. You probably confusing with :
public class MaxPQ implements Comparable<Key> {
...
}
I assume it was decided to use extends for both interfaces and classes, because in the case of generic class declaration it does not make any difference is type argument bound to interface or to class.
Of course meaning of extends is quite different from its typical usage in class definition. Angelika Langer do have nice text about different meanings of extends in Java: Does "extends" always mean "inheritance"?

Categories

Resources