Java Generic how to change parameterized subclass - java

I have such structure:
public class Record{}
public class ParsedRecord extends Record {}
public class RecordsList extends ParsedRecord {}
public abstract class Processor<T extends Record >{ private BlockingQueue<T> queue;}
public class Dispatcher extends Processor<ParsedRecord> {
List<ParsedRecord> list;
public Dispatcher() {
}
public void process(ParsedRecord record){
//blabla
}
}
I want to use Dispatcher class with parameters that are ParsedRecord or any type that extends from ParsedRecord class.
Could some please help me to understand how to properly change Dispatcher class definition?

Could be as simple as changing your class definition to:
public class <T extends ParsedRecord> Dispatcher extends AbstractProcessor<T> {
and then: use that T as type for your list, or for the parameter given to process().
But the real answer here is: study the concept. Don't try to go with trial and error.

You declare a Processor class but you extend AbstractProcessor.
You have probably do a naming mistake in the question.
So I suppose you have only an AbstractProcessor class to give a concrete answer.
In your case, if you want related the type declaration of the class with the parameter of the method, you have to declare the method in the parent class first and specify the parameter of it with the declared type :
public abstract void process(T record){
You would have a parent class :
public abstract class AbstractProcessor<T extends Record >{
...
public abstract void process(T record);
...
}
And in the subclass you get this symmetric declaration :
public class Dispatcher extends AbstractProcessor<ParsedRecord> {
...
public void process(ParsedRecord record){
//blabla
}
}

Related

Override class of parameter in method if it extends that of parameter used in abstract method

Suppose I have the following four classess, out of which two are abstract and two are concrete: Abstract1, Concrete1, Abstract2, Concrete2.
Concrete1 extends Abstract1 and Concrete2 extends Abstract2.
Suppose I have the following four classess, out of which two are abstract and two are concrete: AbstractProp, ConcreteProp, AbstractClass, ConcreteClass.
ConcreteProp extends AbstractProp and ConcreteClass extends AbstractClass.
The code for AbstractClass would look like the following:
public abstract class AbstractClass {
protected AbstractProp someProperty;
public abstract void setProperty(AbstractProp someProperty);
}
When implementing ConcreteClass, I want to be able to do something like this (keep in mind that AbstractProp extends `ConcreteProp):
public class ConcreteClass extends AbstractClass {
#Override
public void setProperty(ConcreteProp someProperty) {
this.someProperty = someProperty;
}
}
But this last bit of code isn't valid because the classes of the parameters (AbstractProp and ConcreteProp) in setProperty() differ, making the #Override annotation invalid. Is there a way I can accomplish what I'm trying to do here, perhaps using generics and/or wildcards?
NOTE: I'm aware that this type of naming is bad practice and the code is oversimplistic, I'm not actually using it and this is just an example to keep the question as simple as possible.
If you introduce generics on the AbstractClass you can achieve what you are requesting.
public abstract class AbstractClass<T extends AbstractProp> {
protected T someProperty;
public void setProperty(T someProperty) {
this.someProperty = someProperty;
}
}
And then specify that you want ConcreteProp to be the type you want in your ConcreteClass.
public class ConcreteClass extends AbstractClass<ConcreteProp> {
#Override
public void setProperty(final ConcreteProp someProperty) {
this.someProperty = someProperty;
}
}

Unexpected bound

I'm trying to compile this new class :
public class WindowedGame
extends GameContainer<GameType extends Game<Graphics2D>> {
...
}
This class extends the class :
public abstract class GameContainer<GameType extends Game<?>> {
....
}
Can you suggest me a correction or explain to me why I get the error :
Unexpected bounds
Thanks!
GameType is the generic type parameter name, so it cannot be in the extends clause.
If WindowedGame should be generic, define it as
public class WindowedGame<GameType extends Game<Graphics2D>>
extends GameContainer<GameType> {
...
}
If WindowedGame shouldn't be generic, perhaps you meant to define it as
public class WindowedGame
extends GameContainer<Game<Graphics2D>> {
...
}
BTW, the naming convention for generic type parameter names is often a single upper case character (T, E, etc...). It would be less confusing if instead of GameType you write T.
public class WindowedGame<T extends Game<Graphics2D>>
extends GameContainer<T> {
...
}
public abstract class GameContainer<T extends Game<?>> {
....
}

Overriding Method with Generic Parameters from Abstract Class

I am unable to compile a method which needs to override a method from an abstract class supertype which uses generics for one of the parameters. The compiler complains that the extending class' setRef() method does not override a method from the supertype.
Parent Abstract Class:
public abstract class AbsClass<Q extends Interf> {
public abstract Ref<? extends AbsClass<Q>> getRef();
public abstract <M extends AbsClass<Q>> void setRef(Ref<M> newRef);
}
Ref is:
public interface Ref<M extends AbsClass<? extends Interf>> { }
and Interf is:
public interface Interf { }
Extending Child Class (setRef() doesn't compile):
public class ChildClass extends AbsClass<InterfImpl> {
#Override
public Ref<ChildClass> getRef() {
return null;
}
#Override
public <M extends ChildClass> void setRef(Ref<M> newRef) {
return null;
}
}
I have also tried using wildcards, and received same error. With wildcards, the abstract class' setRef() is:
public abstract void setRef(Ref<? extends AbsClass<Q>> newRef);
and the extending class' setRef() is:
public void setRef(Ref<ChildClass> newRef)
or even:
public void setRef(Ref<? extends ChildClass> newRef)
The only way I can get it to compile is if the extending class' setRef() uses the abstract class' type:
public <M extends AbsClass<Interf>> void setRef(Ref<M> newRef)
But I would like to limit the typing of the newRef parameter to be Ref<ChildClass> or subtypes, so this isn't perfect. How can I get my extending class to only allow ChildClass or its subtypes for the setRef() method's newRef parameter? Part of my confusion is that the ChildClass' getRef() return value handles the generic typing just fine, and the same "signature" on setRef()'s parameters fails to compile. Help? Thanks!
The problem with setRef is that you could access an instance of ChildClass through a variable of type AbsClass<? extends Interf> and thus the parameter type for setRef would look like <M extends AbsClass<? extends Interf>> which again could be any M but which also doesn't match <M extends AbsClass<Q>> since Q has been defined to be InterfImpl in your case.
You could change ChildClass to this:
public <M extends AbsClass<InterfImpl>> void setRef(Ref<M> newRef)
but this would still allow any M and you can't just use Ref<ChildClass> because what I said above, i.e. the compiler wouldn't know about Ref<ChildClass> if you used a variable of type AbsClass<InterfImpl> or even AbsClass<? extends InterfImpl>.
One way to allow only for ChildClass parameters would be to use ChildClass in the generic type as well, e.g. like this:
public abstract class AbsClass<Q extends Interf, M extends AbsClass<Q, M>> {
public abstract Ref<M> getRef();
public abstract void setRef(Ref<M> newRef);
}
public class ChildClass extends AbsClass<InterfImpl, ChildClass> {
public Ref<ChildClass> getRef() { return null; }
public void setRef(Ref<ChildClass> newRef) { }
}
You are getting an error because in AbsClass.setRef(), your parameter is of type Ref<? extends AbsClass<Q>>
But in your ChildClass.setRef() the parameter is of type Ref<? extends ChildClass>.
For overriding, a subclass should have the same typed parameters in the method as it's parent (before type erasure when using Generics).

Type check parameter is a (sub)class and also implements an interface

This answer no doubt exists on SO, but I haven't found the right combination of search terms to come up with it.
I have a method that I want to take a parameter that is of class A, but also implements interface B. How do I do it?
e.g.
public class MySubclassWithInterface extends MyClass implements MyInterface { }
public class MySubclass extends MyClass { }
public class MyInterfaceClass implements MyInterface { }
public class MyOtherSubclassWithInterface extends MyClass implements MyInterface { }
Out of the three classes above, I only want my method to accept an object that is MyClass and implements MyInterface, in other words, either MySubclassWithInterface or MyOthersubclassWithInterface but not MySubclass or MyIntefaceClass
I very sheepishly tried the following which obviously failed:
public void myMethod( (MyClass MyInterface) parameterName) {
...
}
Thanks for your help in advance.
You can express this with a generic type as in the following signature:
<T extends MyClass & MyInterface> void m(T p)
The rule is that the first type must be a class or an interface and any following parameter must be an interface type.

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