Extending Generic Abstract Class & Correct Use of Super - java

public abstract class AbstractTool<AT extends AbstractThing> {
protected ArrayList<AT> ledger;
public AbstractTool() {
ledger = new ArrayList<AT>();
}
public AT getToolAt(int i) {
return ledger.get(i);
}
// More code Which operates on Ledger ...
}
public class Tool<AT extends AbstractThing> extends AbstractTool {
public Tool() {
super();
}
}
How do I correctly call super to pass the AT generic of Tool to the AbstractTool constructor?
It seems no matter what I pick AT to be when I declare Tool (Say, Tool<Thing>), that I always get back an AbstractThing instead of Thing. This seems to defeat the purpose of generics...
Help?

public class Tool<AT extends AbstractThing> extends AbstractTool<AT> {
In other words, if you extend or implement something with generics, remember to define the generics arguments for them.

Shouldn't it rather be
Tool<AT extends...> extends AbstractTool<AT>?

I think what you probably want is:
public abstract class AbstractTool<AT extends AbstractThing> {
protected List<AT> ledger = new ArrayList<AT>();
public AT getToolAt(int i) {
return ledger.get(i);
}
// More code Which operates on Ledger ...
}
public class Tool extends AbstractTool<Thing> {
// Tool stuff ...
}
Since Tool is a concrete class, it doesn't need to be parametrized itself. There is no need for the constructors if you initialize the List (oh and remember to program to the interface) at declaration, and because it is protected the subclasses can access it directly.

Related

Java generic : Restricting a class to specific implementations.

I have the following class hierarchy:
public abstract class Config<T> implements Proxy<T> {
public abstract T parse();
public T get() {....}
}
public class IntegerConfig<Integer> extends Config<Integer> {
public Integer parse() {...}
}
public class LongConfig<Long> extends Config<Long> {
public Long parse() {...}
}
public class IntegerListConfig<List<Integer>> extends Config<List<Integer>> {
public List<Integer> parse() {....}
}
And so on...
I'd like to introduce a new class:
public class ConfigMutation<T> implements Proxy<T> {
public ConfigMutation(....) {
//// create a concrete implementation of Config<T> according to actual parameterized type
}
}
Essentially, I'd like to avoid repeating the entire class hierarchy of Config, and support in ConfigMutation all types that have parameterized implementations in Config class hierarchy.
Couldn't find a way to do it. (Class<T>)((ParameterizedType)getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0] obviously returns T, and not the actual type.
Also, once this problem is solved, I'd be happy if someone could suggest some factory pattern with generic types, so when I'm instantiating a Config derived class inside ConfigMutation, I wouldn't have to do it with a huge if...else block on actual type.
Thanks,
Lior
Change your ConfigMutation class to :
public class ConfigMutation<U,T extends Config<U>> implements Proxy<U> {
public ConfigMutation() {
}
}
You can then use ConfigMutation as :
ConfigMutation<Integer,IntegerConfig> mutation;
You won't be able to do something as follows which is what you want :
ConfigMutation<String,IntegerConfig> mutation;
That said, there is a change you need to make to your concrete Config implementers as well. For example, change IntegerConfig to :
public class IntegerConfig extends Config<Integer> {
public Integer parse() {...}
}
The Integer in IntegerConfig<Integer> will be considered as a type parameter and not the Integer class which is not what you want. (An IDE should give you a warning for this; The type parameter Integer is hiding the type Integer)

Bound mismatch with Java Generics "nesting"

I'm having difficulty using generics for a redesign/refactoring I'm doing on an existing design.
public interface DataDto {
// some data here
}
public interface SetDto<MyDataDto extends DataDto> {
List<MyDataDto> getData();
}
public interface Results<MySetDto extends SetDto<DataDto>> {
MySetDto getResults();
}
public interface MyProblemInterface<MyDataDto extends DataDto,
MySetDto extends SetDto<MyDataDto>,
MyResults extends Results<MySetDto>> {
// some stuff here
}
My problem is that I get the following error for MyProblemInterface:
Bound mismatch: The type MySetDto is not a valid substitute for the
bounded parameter <MySetDto extends SetDto<DataDto>> of the type
Results<MySetDto>
I admit my experience with generics is somewhat limited, but basically I'm trying to enforce that all three of the types in MyProblemInterface are the same "type". For example, if I have ADataDto, BDataDto, ASetDto<ADataDto>, BSetDto<BDataDto>, AResults<ASetDto>, BResults<BSetDto>, I want to ensure a class can't implement MyProblemInterface in a manner like AMyProblemInterface<ADataDto, ASetDto, BResults>. I would think that since MySetDto extends SetDto<MyDataDto> just fine, I could continue to take that further, but I'm apparently wrong.
Thank you for any help.
You want too much from Java generics.
It would be simpler to declare your interface as following:
public interface MyProblemInterface<MyDataDto extends DataDto>
And then force method to use SetDto<MyDataDto> and Results<MySetDto>.
By using generics in class/interface declaration you specify some kind of variety which is determined later in definition. But in your case you said that SetDto and Results will always have MyDataDto as parameter, so there is no variety.
Shouldn't it be something like this instead, and you add the actual classes only when implementing the interfaces.
Updated the code, because I forgot to add the right Results definition. This should work.
public interface DataDto {
// some data here
}
public interface SetDto<T extends DataDto> {
List<T> getData();
}
public interface Results<T extends SetDto<? extends DataDto>> {
T getResults();
}
public interface MyProblemInterface<T extends DataDto, E extends SetDto<T>, K extends Results<E>> {
// some stuff here
}

Using 2 levels of generics in an Abstract Class definition

I have this generic interface:
public interface TjbListener<T> {
public void hearChange(T t);
}
Which I use like this:
public interface ObjectOneListener extends TjbListener<ClassOne> {
}
I would like to write an abstract generic class A which takes a generic type U as a parameter and has a method (1) which itself calls a method (2) on U. Below is my attempt U should extend (or implement maybe?) the generic TjbListener interface.
public abstract class ListenerInformer<U extends TjbListener<"what should I write here">> {
List<U> mListeners = new ArrayList<U>();
public void addListener(U u){
mListeners.add(u);
}
public void informAll("what should I write here"){
for(U u:mListeners){
u.hearChange("what should I write here");
}
}
}
One solution I thought of as I was writing this question is below, but I don't know if it's really a solution, or if it has subtle problems I don't understand:
public abstract class ListenerInformer<U extends TjbListener<T>,T> {
List<U> mListeners = new ArrayList<U>();
public void addListener(U u){
mListeners.add(u);
}
public void informAll(T t){
for(U u:mListeners){
u.hearChange(t);
}
}
}
UPDATE: BEWARE
I have just discovered that this approach is almost useless for my particular case because the same class cannot implement the same interface with different parameters. See the question linked below. This means that I cannot have one class be a listener of two different types with my (or Johanna's) solution, without using a different strategy like composition.
How to make a Java class that implements one interface with two generic types?
Your second example should work. But if it is as simple as that, then there is no need for the Generic U, because every instance of a subclass of TjbListener also is an instance of TjbListener.
You can do more simple:
public abstract class ListenerInformer<T> {
List<TjbListener<T>> mListeners = new ArrayList<TjbListener<T>>();
public void addListener(TjbListener<T> u){
mListeners.add(u);
}
public void informAll(T t){
for(TjbListener<T> u:mListeners){
u.hearChange(t);
}
}
}
That works as your code does and is easier to handle.
Two generic types is necessary if you need the final implementation type of the subclass of TjbListener as return value of parameter, for example if you have
public U informAll2(T t){
for(U u:mListeners){
u.hearChange(t);
if (...)
return u;
}
}
In this case your declaration with two generic types is correct (just I'm not sure if it is possible to declare the generic U, which depends of T, before you declare T, of if you have to declare T first, like public abstract class ListenerInformer<T, U extends TjbListener<T>> )

Java inheritance and generics

I'm trying to extend an abstract class with generics and I'm running into a problem:
abstract public class SomeClassA<S extends Stuff> {
protected ArrayList<S> array;
public SomeClassA(S s) {
// ...
}
public void someMethod() {
// Some method using the ArrayList
}
abstract public void anotherMethod() {
// ...
}
}
Now I want to extend this class with another abstract class so I could override "someMethod". I tried:
abstract public class SomeClassB<Z extends Stuff> extends SomeClassA {
public SomeClassB(Z z) {
super(z);
}
#Override public void someMethod() {
// Some method using the ArrayList
}
}
NetBeans doesn't see any problem with the constructor, but I cannot use the ArrayList from SomeClassA within the method someMethod. So I tried:
abstract public class SomeClassB<Z extends Stuff> extends SomeClassA<S extends Stuff> {
public SomeClassB(Z z) {
super(z);
}
#Override public void someMethod() {
// Some method using the ArrayList
}
}
And now it's just very odd. Everything seems to work (and I can now use the arraylist, but NetBeans says there's a "> expected" in the declaration of SomeClassB and it just won't compile. If possible, I would like:
To know how to solve this particular problem.
To have a good reference to understand generics.
To know if it's any easier in C#.
You will need to pass the generic type to the superclass also, like this:
abstract public class SomeClassB<Z extends Stuff> extends SomeClassA<Z>
Your superclass and subclass will then both use the same generic type. Generic Types are not inherited by subclasses or passed down to superclasses.
For a good reference to understand generics, check out Effective Java, 2nd Edition.

Java - Return correct type from Generic method

I have the following class structure:
public class Team {
...
}
public class Event {
}
public abstract class Fixture<T extends Team> implements Event {
...
}
public abstract class Forecast<Event> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends Forecast<Fixture<? extends Team>>{
}
I am trying to model sports events of all kinds (i.e. a 'Fixture' is for a particular game between two participants play against each other, whereas another type of 'Event' may have many participants), along with predictions for the outcome of particular 'Events'. I have a generic method:
public <T> MyPrediction<Fixture<? extends Team>> getMyPrediction(Fixture<? extends Team> fixture) {
}
I want to be able to return a MyPrediction instance which has the generic type of the fixture argument, but I can't seem to do so. For example, if I do something like the following, then I get a compilation error:
SoccerFixture<EnglishSoccerTeams> soccerMatch = new ScoccerFixture<EnglishSoccerTeams>();
MyPrediction<SoccerFixture<EnglishSoccerTeams>> = getMyPrediction(soccerMatch);
I am willing to change my class structure to incorporate this feature. How can I do so?
Change the signature of getMyPrediction to
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture)
This tells the compiler that the fixture types in the argument and result are the same, allowing type-checking to pass.
Here is a complete example, with some other minor changes to get it to compile. It introduces the class Predictor to hold the getMyPrediction method and a doit method to show sample use:
public interface Team {
}
public interface Event {
}
public abstract class Fixture<T extends Team> implements Event {
}
public abstract class Forecast<T> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends
Forecast<Fixture<? extends Team>> {
}
public class SoccerFixture<T extends SoccerTeam> extends Fixture<T> {
}
public class SoccerTeam implements Team {
}
public class EnglishSoccerTeam extends SoccerTeam {
}
public class Predictor {
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture) {
return new MyPrediction<T>();
}
public void doit() {
SoccerFixture<EnglishSoccerTeam> soccerMatch = new SoccerFixture<EnglishSoccerTeam>();
MyPrediction<SoccerFixture<EnglishSoccerTeam>> myPrediction = getMyPrediction(soccerMatch);
}
}
As noted elsewhere, you might need to introduce one or more factory objects to perform meaningful work in the MyPrediction implementation.
Java's type system is not powerful enough to do directly what you propose, because of type erasure (the generic parameters are not available at runtime.
The usual solution is to create a separate EventFactory class, which you can then pass in to any method which needs to create a specific Event subtype instance.

Categories

Resources