Java - Handling generics with inheritance - java

I have a class that represents a vendor service and all their services have an authentication and an execute method.
I started thiking of an abstract class that represents this as below.
The thing is each of their services require a different request object, so I thought of using generics.
The problem is that if use it, I can't handle the specifics of each request object. Each children must use some methods from the type.
1) Should I try to make this way I'm trying, or remove this executeRequest method from the abstract class and each subclass implement it with the correct type?
2) I always hear "prefer composition over inheritance". Should I move the executeRequest to an interface?
Thanks in advance!
public abstract class VendorService {
private final VendorInitialization VendorInitialization;
//a bean with some auth params
public VendorService(VendorInitialization VendorInitialization) {
this.VendorInitialization = VendorInitialization;
}
protected abstract <T> boolean validateRequest(T requestObject) throws VendorServiceBadRequest;
protected abstract <T, P> P executeRequest(T requestObject);
}
public class VendorServiceAllocation extends VendorService {
public VendorServiceAllocation(VendorInitialization VendorInitialization) {
super(VendorInitialization);
}
#Override
protected <T> boolean validateRequest(T requestObject) throws VendorServiceBadRequest {
//List<BeanAllocation> requestObject = new Arraylist<>(); //I was using like this before
//TODO: how to handle it as list of on this specific case?
if (requestObject == null || requestObject.size() == 0) {
throw new VendorServiceBadRequest(String.format("The list must have at least one element"));
}
//TODO: requestObject.get(0).getMySpecificFieldFromBeanAllocation will not work
//some checks
return true;
}
#Override
protected <T, P> P executeRequest(T requestObject) {
//executes and return a list of objects specific to this class
return new List<BeanAllocationResponse>();
}
}
Edit, for clarification:
In the child class VendorServiceAllocation, I need to use some methods that are specific of that type.
E.g.: Inside executeRequest, I need to call requestObject.customFunctionFromChild()

I think niceman hit the nail on the head, though I am not quite sure what you are asking. eg.
abstract class Service<T,P>{
abstract public P processRequest(T t);
}
Then you can implement it in one of two ways.
class StringService extends Service<String, String>{
public String processRequest(String t){
return t;
}
}
Or you could leave it to still be Generic and the actual instances would have the different types.
class OtherService<T> extends Service<T, String>{
public String processRequest(T t){
return t.toString();
}
}
Where you could use it as,
OtherService<Integer> is = new OtherService<>();

Related

Java generics wildcard for different subtypes clarification

I want to avoid explicit cast in my code, this is what I've done until now, but the compiler gives me some error and I don't understand how to fix it without cast.
I have a class with a map of listener, and some methods which notify the listeners:
public class MessageDispatcher {
private final Map<String, List<ControllerMessageWatcher<? extends ControllerMessage>>> watchers;
public void registerMessageWatcher(Class<? extends ControllerMessage> classToWatch, final ControllerMessageWatcher<?> controllerMessageWatcher) {
this.watchers.computeIfAbsent(classToWatch.getSimpleName(), k -> new ArrayList<>()).add(controllerMessageWatcher);
}
public synchronized void receive(StatusMessage statusMessage) {
List<ControllerMessageWatcher<?>> watchers = this.watchers.get(statusMessage.getClass().getSimpleName());
if (watchers != null)
watchers.forEach(controllerMessageWatcher -> controllerMessageWatcher.newMessage(statusMessage));
// Required type: capture of ? Provided: StatusMessage <-- error here! ^^^^
}
public synchronized void receive(UpdateDBMessage updateDBMessage) {
List<ControllerMessageWatcher<?>> watchers = this.watchers.get(updateDBMessage.getClass().getSimpleName());
if (watchers != null)
watchers.forEach(controllerMessageWatcher -> controllerMessageWatcher.newMessage(updateDBMessage));
// Required type: capture of ? Provided: UpdateDBMessage <-- error here! ^^^^
}
}
This is the interface for the listeners:
public interface ControllerMessageWatcher<T extends ControllerMessage> {
void newMessage(T message);
}
And this is the implementation of listener that I wish use avoiding casting:
public class Status implements ControllerMessageWatcher<StatusMessage> {
#Override
public void newMessage(StatusMessage message) {
...
}
}
All works except the methods receive which gives errors (or unchecked warnings if I remove wildcards).
What I want to achieve is avoid explicit cast in every newMessage methods (I have to do this if I remove all generics part).
And avoiding errors/warnings when I call newMessage from MessageDispatcher.receive() methods (what I have now) (see comments in that methods)
This are ControllerMessage, StatusMessage and UpdateDBMessage:
public abstract class ControllerMessage {
private String messageId;
// ... getter setter
}
public class StatusMessage extends ControllerMessage{
private String aField;
// ... getter setter
}
public class UpdateDBMessage extends ControllerMessage{
private String aField;
// ... getter setter
}
I think your design is fundamentally broken because of your use of reflection.
public void registerMessageWatcher(
Class<? extends ControllerMessage> classToWatch,
final ControllerMessageWatcher<?> controllerMessageWatcher
)
This step, at the level of your API, you have made it impossible for the compiler to manage your inheritance.
A small improvement would be to make the type consistent.
public <T extends ControllerMessage> void registerMessageWatcher(
Class<T> classToWatch,
final ControllerMessageWatcher<T> controllerMessageWatcher
)
Now we are keeping track of our class type, for better or worse, but we still need to caste to keep the classes in the map.
private final Map<Class<?>, List<ControllerMessageWatcher<?>>> watchers;
List<ControllerMessageWatcher<T>> getWatchers( Class<T> clazz ){
return (List<ControllerMessageWatcher<T>>)watchers.get(clazz);
}
To avoid casting I would make
public interface ControllerMessageWatcher<T extends ControllerMessage> {
void newMessage(ControllerMessage message);
}
I don't know what you're doing with your watcher that would new message to distinguish the type. This way you can have.
List<ControllerMessageWatcher<? extends ControllerMessage>> watchers;
watchers.forEach( w -> w.newMessage( message ) );
Then replace the abstract classes with interfaces.
interface ControllerMessage{
String getMessageId();
String getAField();
}
Now it is up to the specific watchers to grab the relevant information. You can also make default methods for fields that are not relevant.

Java dealing with a lot of concrete factories

I want to generalize a repetitive piece of Java code for a lot of (~40-50) similar entities (in my case, this piece is indexing of files with these entities).
I tried to refactor it with generic method, but, as a result, I get a constructor of generic class that is apparently prohibited in Java. To avoid this, I implemented abstract factory pattern and here's what I've get.
public <E extends CMObject, F extends IndexedFile<E>> F indexFile(CMFactory<E, F> factory) {
F items;
ByteBuffer[] buffs;
// ...filling buffers...
items = factory.makeFile(buffs); // as I cannot do items = new F(buffs)
return items;
}
public CityFile getCities() {
return indexFile(new CityFactory());
}
public ContinentFile getContinents() {
return indexFile(new ContinentFactory());
}
// a lot of more
This solves an issue of creating an instance of generic class. However, I now face a task of creating a concrete factory for each single entity that seems to be a lot of monotonous work as they all look like each other.
public abstract class CMFactory<E extends CMObject, F extends IndexedFile<E>> {
public abstract F makeFile(ByteBuffer[] buff);
}
public class CityFactory extends CMFactory<City, CityFile> {
#Override
public CityFile makeFile(ByteBuffer[] buff) {
return new CityFile(buff);
}
}
public class ContinentFactory extends CMFactory<Continent, ContinentFile> {
#Override
public ContinentFile makeFile(ByteBuffer[] buffs) {
return new ContinentFile(buffs);
}
}
The question is: is there any way to automatize creation of such factories? Or maybe is there another pattern that can at least make such creation less painful?
I tried to use IntelliJ IDEA's Replace Constructor with Factory Method refactor, but it didn't help me.
Since your CMFactory is almost a functional interface you can use constructor handles instead of implementing CMFactory for each concrete class:
Make CMFactory an interface:
public interface CMFactory<E extends CMObject, F extends IndexedFile<E>> {
public abstract F makeFile(ByteBuffer[] buff);
}
and then write
public CityFile getCities() {
return indexFile(CityFile::new);
}
You can even discard CMFactory and use java.util.Function:
public <E extends CMObject, F extends IndexedFile<E>> F indexFile(Function<ByteBuffer[],F> factory) {
ByteBuffer[] buffs;
// ...filling buffers...
return factory.apply(buffs);
}

Java generics involving inheritance and this

I have a (for me) complex Java generics problem. I read through some documentation and understand some but certainly not all of what I should. Basically, for me, trying to solve it would result in try and error.
In the following, I give a condensed example of my code, once without any generics (so one can hopefully understand what I want to achieve) and the other with some additions that come closer to the solution. Please correct my second version and/or point me to specific documentation. (I have general documentation of Java generics. But my code seems to have several interfering challenges and it is hard to a correct solution)
About my example: There is an abstract base type and several implementing variants (only one is given). Method combine() calls getOp1(), which decides (depending on <some condition>) if it should operate on its own instance or on a new one. After the calculation, it returns the target instance.
abstract class Base {
protected final Base getOp1() {
if(Util.isConditionMet()) { return getNewInstance(); }
else { return this; }
}
protected abstract Base getNewInstance(); // returns a new instance of an implementing class
public abstract Base combine(Base other);
}
class Variant extends Base {
public Variant getNewInstance() { return new Variant(); }
public combine(Variant op2) {
Variant op1 = getOp1();
op1.calculate(op2);
return op1;
}
private void calculate(Variant other) { /* some code */ }
}
The version with some generics added. This version is faulty and does not compile.
abstract class Base<T extends Base<T>> {
protected final T getOp1() {
if(Util.isConditionMet()) { return getNewInstance(); }
else { return this; }
}
protected abstract T getNewInstance(); // returns a new instance of an implementing class
public abstract T combine(T other);
}
class Variant<T extends Variant<T>> extends Base<T> {
protected T getNewInstance() { return new Variant(); }
public T combine(T op2) {
T op1 = getOp1();
op1.calculate(op2);
return op1;
}
private void calculate(T other) { /* some code */ }
}
To make this code working, you need to resolve incompatibility type issues: replace T returning types by Base<T> and cast result of Variant#getOp1() to Variant<T> to allow invoke calculate() on it (this is safe here because Variant#getOp1() always returns Variant:
abstract class Base<T extends Base<T>> {
protected final Base<T> getOp1() {
return condition() ? getNewInstance() : this;
}
protected abstract Base<T> getNewInstance();
public abstract Base<T> combine(T other);
}
class Variant<T extends Variant<T>> extends Base<T> {
protected Base<T> getNewInstance() {
return new Variant();
}
public Base<T> combine(T op2) {
Variant<T> op1 = (Variant<T>) getOp1(); // <- explicit cast
op1.calculate(op2);
return op1;
}
private void calculate(Base<T> other) {
// ...
}
}
Btw, I still see no reason of such complicated type structure.
I have seen a couple of such combinational, operational classes, though never too elaborate. Maybe inheritance is not the right tool.
Better to use a lookup mechanism for capabilities, features.
class Base {
// Untyped
private Map<Class<?>, Object> capabilities = new HashMap<>();
protected <I> void register(Class<I> intf, I obj) {
capabilities.put(intf, obj);
}
public <T> Optional<T> lookup(Class<T> intf) {
Object obj = capabilities.get(intf);
return obj == null ? Optional.emtpy() : Optional.of(intf.cast(obj));
}
}
interface Flying {
void fly(double altitude);
}
Base pelican = new Pelican();
Flying flying = pelical.lookup(Flying.class).orElse(null);
flying.fly(0.5);
This also allows dynamic changes, and combining things with respect to two aspects.

Force a generic type to be an interface?

It looks like this is impossible to do, but does anyone have a clever way around this problem?
public class SomeClassIterableWrapper<S, T extends SomeClass & S> implements Iterable<S>
Where S is supposed to be an interface of some unknown type and SomeClass is a 2D array with a row index, similar in functionality to a bidirectional JDBC resultset. Subclasses of SomeClass have custom getters and setters for each column. I want to be able to iterate through this structure like I would a List. I want to implement a common interface between my SomeClass and Bean to have access to the getters and setters. As such S needs to be that interface. However the declaration I provided does not work. Is there a way to work around this?
edit to show my desired implementation:
public class SomeClassIterableWrapper<S, T extends SomeClass & S> implements Iterable<S>{
T object;
public SomeClassWrapper(T object){
this.object = object;
}
#Override
public Iterator<S> iterator() {
object.setIndex(-1);
return new SomeClassIterator<S>();
}
private class SomeClassIterator<S> implements Iterator<S> {
#Override
public boolean hasNext() {
return object.index() < object.rowSize() - 1;
}
#Override
public S next() {
object.next();
//safe because only interface methods allowed, can't further manipulate index
return object;
}
#Override
public void remove() {
object.deleteRow();
}
}
Can't you parameterize SomeClass with S? Then you could have
public class SomeClassIterableWrapper<S, T extends SomeClass<S>>
implements Iterable<S>{
I think the S in extends SomeClass & S
public class SomeClassIterableWrapper
has to be a definite class because in this context,
S has to be a class that is extending something.
Is there a way you can narrow down what the
potential classes that are used in place of S are?
You could use multiple ampersands if you have multiple
classes that T should extend
I confess that I don't fully comprehend the problem but this is what I suggest:
Create an interface of S. It contains one method ad it returns the S object.
public interface SWrapper<S> {
S getS();
}
Then create an implementation:
public class SImpl implements SWrapper<SImpl> {
#Override
public SImpl getS() {
return this;
}
}
You can now create:
public class SomeClass<T extends SomeClass & SWrapper<T>> {
private final T object;
public SomeClass(T object) {
this.object = object;
}
}
You will have to modify your usage a bit but perhaps it works.

Is it possible declare and implement a method once, but vary the return type to match subinterfaces in a robust manner?

First off, I want to say there is no use case for this. The only thing I am trying to do is explore if this is possible.
What I am trying to do is "rebrand" the return signature of a method in the base interface to that of a child interface.
The goal: declare and implement a method once, but vary the return type to match subinterfaces. I have figured out how to achieve this in some cases, but it breaks down in certain situations.
Imagine if I have base interface B and it has a method B doWork(). Also, there is an implementation of B that implements doWork(). Due to the nature of doWork(), this implementation should be the only one that exists.
Now, this is pretty easy to do with Generics. For the above example:
interface B<T extends B> {
T doWork();
}
class BImpl<T extends B> implements B<T> {
#Override
public T doWork() { return something; }
}
And the child interface/impl would look like this maybe:
interface C extends B<C> {
void somethingCSpecific();
}
class CImpl extends BImpl<C> implements C {
#Override
public void somethingCSpecific() { }
}
Anyone constructing CImpl would see that doWork() returns a C.
C obj = new CImpl().doWork() // The money shot. No casting needed.
And here is where it breaks down... Imagine B now looks like this:
public interface B<T extends B> {
T thisOrThat(T that);
boolean something();
}
And I want to do this in BImpl:
class BImpl<T extends B> implements B<T> {
#Override
public T thisOrThat(T that) {
if (that.something())
return that;
return this; // Error!! _this_ might be a different T than _that_.
}
#Override
public boolean something() { return whatever; }
}
Note where the error happens.
Obviously, this can't work without an unsafe and dubious cast. But if I knew that the implementation of this in the above thisOrThat method was the same as the implementation of that, everything would be ok.
So, to my question. Is there a way to restrict this and that to the same type, without knowing that type a priori?
Or maybe is there a different way to go about doing this, but having the same result? Namely only having to declare AND implement thisOrThat() just once, yet have the return type adapt to the subinterface?
Thanks.
Make your class BImpl abstract and add a view method to it which is implemented by the specific classes extending your abstract base class:
public abstract class BImpl<T extends B<T>> implements B<T> {
#Override
public T thisOrThat(T that) {
if (that.something())
return that;
return this.asT();
}
#Override
public boolean something() {
// TODO Auto-generated method stub
return false;
}
protected abstract T asT();
}
Every of your classes still needs to implement T asT() then, but this is simple and compiles without warning:
public class C extends BImpl<C> implements B<C> {
#Override
protected C asT() {
return this;
}
}
If I understand your problem correctly, then the way to solve it is with a sort of self-referential generic: B<T extends B<T>>.
I think what you want is class BImpl implements B<BImpl>, in which case everything type checks normally.

Categories