Java Generic Interfaces with multiple implementations - java

I have the following scenario:
public abstract class BaseTask{...}
public class TaskA extends BaseTask {....}
public class TaskB extends BaseTask {....}
public interface TaskService<T extends BaseTask>{
void process(T task);
}
#Service #Qualifier("taskServiceA")
public class TaskServiceA<TaskA> implements TaskService<TaskA>{
}
#Service #Qualifier("taskServiceB")
public class TaskServiceB<TaskB> implements TaskService<TaskB>{
}
public class ProcessingService{
#Autowired #Qualifier("taskServiceA")
private TaskService<TaskA> taskAService;
#Autowired #Qualifier("taskServiceB")
private TaskService<TaskB> taskBService;
public void process(Order o){
BaseTask task = o.getTask();
getTaskService(o).start(task);
}
private <T extends BaseTask> TaskService<T> getTaskService(Order o){
if("atype".equals(o.type)){
return (TaskService<T>) taskAService;
} else if("btype".equals(o.type)){
return (TaskService<T>) taskBService;
}
}
}
Update: I have reworded the question because the answers I was getting was not what I was looking for.
My questions is related to the getTaskService method.
Why do I need to cast the return value like this
return (TaskService) taskAService;
Is there another way to implement the getTaskService() method without having to do the cast?
I will really appreciate if someone can provide some explanation or better implementation for the getTaskService method.

How about this?
No need of any if conditions.
Later if someone does add another implementation of BaseTask they don't have to change any other code.
Also I recommend changing "atype" to Enum and using Map<EnumTask, ? extends BaseTask> serviceMap; instead of String.
Your final invocation of Tasks can be without any checks
#Service
class ProcessingService {
#Autowired
private TaskServiceManager taskServiceManager;
public void process(Order o){
taskServiceManager.getServiceTask(o.type).start(task);
}
}
Other classes
enum ServiceEnum {
TaskA,
TaskB
}
public class TaskA extends BaseTask {....}
public class TaskB extends BaseTask {....}
public abstract class TaskService<T extends BaseTask>{
public TaskService(ServiceEnum serviceEnum, TaskServiceManager taskServiceManager) {
taskServiceManager.registerTask(serviceEnum, this);
}
void process(T task);
}
#Service #Qualifier("taskServiceA")
public class TaskServiceA<TaskA> implements TaskService<TaskA>{
#Autowired
public TaskA(TaskServiceManager taskServiceManager) {
super(ServiceEnum.TaskA, taskServiceManager);
}
}
#Service #Qualifier("taskServiceB")
public class TaskServiceB<TaskB> implements TaskService<TaskB>{...}
#Service
class TaskServiceManager {
Map<ServiceEnum, ? extends TaskService> serviceMap;
public <T extends TaskService> void registerTask(ServiceEnum serviceName, T task) {
if(serviceMap.containsKey(serviceName)) {
throw new IllegalArgumentException("ServiceName is already in the Map");
}
serviceMap.put(serviceName, task);
}
public <T extends TaskService> T getServiceTask(ServiceEnum serviceName) {
if(!serviceMap.containsKey(serviceName)) {
throw new IllegalArgumentException("ServiceName is not Registered");
}
return serviceMap.get(serviceName);
}
}

Because type T is resolved wherever the method is used. The following statement is valid:
TaskService<TaskA> s = getTaskService(o);
So is:
TaskService<TaskB> s = getTaskService(o);
So within the method getTaskService, you don't know much about T.
The correct way to do this would be:
private TaskService<? extends BaseTask> getTaskService(Order o) {
if ("atype".equals(o.type)) {
return taskAService;
} else if ("btype".equals(o.type)) {
return taskBService;
} else {
return null;
}
}
The assignment above would have to become:
TaskService<? extends BaseTask> s = getTaskService(o);

Related

I don't understand why my generic type declaration doesn't match

Here are the classes declarations:
public interface IPoint<N extends Number> {
...
}
public abstract class PointP<N extends Number> implements IPoint<N> {
...
}
public class Pointf extends PointP<Float> {
...
}
public interface ISegment<T extends Number, P extends IPoint<T>> {
...
}
public abstract class SegmentP<N extends Number, P extends IPoint<N>> implements ISegment<N, P> {
...
}
public class Segmentf extends SegmentP<Float, Pointf> {
...
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, IPoint<N>>> implements Iterable<S>, Iterator<S> {
...
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
...
}
The compiler refuses the Segmentf type in the generic declaration of the LinesfIterator class with the error message:
Bound mismatch: The type Segmentf is not a valid substitute for the bounded parameter <S extends ISegment<N,IPoint<N>>> of the type LinesPIterator<N,S>
However for me everything seems correct. The declaration of the LinesfIterator class seems to me to have the same hierarchical schema as the Segmentf class which compiles without problem.
Is there a solution to this way of doing things?
As already said, your hierarchy seems to be unnecessarily complex and shall be simplified. For example, I see no meaning in Pointf -> PointP -> IPoint the hierarchy.
If you want to fix your issue, you have to allow a subtype ? extends IPoint<N> in the LinesPIterator class, so:
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>>
implements Iterable<S>, Iterator<S>
{
// ...
}
Moreover, there would be better to implement only Iterable as long as it provides an Iterator and you might end up with duplicated implementation.
public static class LinesfIterator extends LinesPIterator<Segmentf, Pointf, Float> {
#Override
public Iterator<Segmentf> iterator() {
return new Iterator<Segmentf>() {
#Override
public boolean hasNext() { /* TO DO */ }
#Override
public Segmentf next() { /* TO DO */ }
};
}
}
This remark on the use of an anonymous class rather than a direct use really caught my attention because intuitively, when I can avoid going through an anonymous class I do. On the one hand because it is an additional instantiation and on the other hand because it is more difficult to identify at debug (when they are several in the same class).
And I can't see the reasons why I should prefer the use of an anonymous class for this case.
Maybe with my classes as an example the explanation will be easier.
for(Segmentf segment : new LinesfIterator(cube.getPoints(), cube.getIndices())) {
System.out.println(segment);
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>> implements Iterable<S>, Iterator<S> {
private N[][] points;
private int[] indices;
private int count;
public LinesPIterator(N[][] points, int[] indices) {
super();
this.points = points;
this.indices = indices;
}
protected abstract S instanciateIteration(final N[] pointDeb, final N[] pointFin);
#Override
public Iterator<S> iterator() {
return this;
}
#Override
public boolean hasNext() {
return count < (indices.length - 1);
}
#Override
public S next() {
return instanciateIteration(points[indices[count++]], points[indices[count++]]);
}
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
public LinesfIterator(Float[][] points, int[] indices) {
super(points, indices);
}
#Override
protected Segmentf instanciateIteration(Float[] point1, Float[] point2) {
return new Segmentf(point1, point2);
}
}

Java return ArrayList<MyObject> in medhot which returns an ArrayList of an Interface

I have two classes which have to getMethodes which returns an ArrayList of two Objects which implements a interface
public class MyClass1 implements IMyClasses<MyObject1>{
public ArrayList<MyObject1> getMyObject() { ... }
}
public class MyClass2 implements IMyClasses<MyObject1>{
public ArrayList<MyObject1> getMyObject() { ... }
}
MyObject1 and MyObject2 implements IMyObject
In my ManagerClass I would like to implement a function which can return any IMyObject implementation
ArrayList<IMyObject) get() {
if (...) {
return new MyClass1().getMyObject();
} else {
return new MyClass2().getMyObject();
}
}
Before I have introduced the Generic typ on MyClass1 and MyClass2 it worked fine, but with the Generic which I need to get the proper object if needed, I'm not able to return the object which has as return type the Interface?
Some help?
Edit this is a full working example, the trick is to do <? extend IMyObject> thx to #Alexander.Furer
public class ManagerClassTest {
public interface IManagerClass {
public ArrayList<? extends IMyObject> getMyObject(boolean myObject1);
}
public interface IMyClass<I>{
public ArrayList<I> getMyObject();
}
public interface IMyObject {}
public class MyObject1 implements IMyObject {}
public class MyClass1 implements IMyClass<MyObject1> {
#Override
public ArrayList<MyObject1> getMyObject() {
return new ArrayList<MyObject1>();
}
}
public class MyObject2 implements IMyObject {}
public class MyClass2 implements IMyClass<MyObject2> {
#Override
public ArrayList<MyObject2> getMyObject() {
return new ArrayList<MyObject2>();
}
}
public class ManagerClass implements IManagerClass {
private ArrayList<MyObject1> getMyObject1() {
return new MyClass1().getMyObject();
}
private ArrayList<MyObject2> getMyObject2() {
return new MyClass2().getMyObject();
}
#Override
public ArrayList<? extends IMyObject> getMyObject(boolean myObject1) {
if (myObject1) {
return new MyClass1().getMyObject();
} else {
return new MyClass2().getMyObject();
}
}
}
}
ArrayList<MyObject1> is not of type ArrayList<IMyObject> ,BTW, you have a typo :ArrayList<IMyObject)
Declare the get method of ManagerClass as :
ArrayList<? extends IMyObject> get() {
}

Abstract class with visitor - similar to typeOf

I am little confused how to avoid using casing in my manager method (last snippet of code) in terms of abstract class with it's derived classes (entities) and visitor design pattern eventually. Below I have an abstract class for entities called BaseEntity. It's not a real example, just pseudocode.
public abstract class BaseEntity {
#Reference
protected List<String> items = new ArrayList<>();
public BaseEntity() {
}
public List<String> getItems() {
return items;
}
public void setItems(List<String> items) {
this.items = items;
}
}
Below I have 3 derived classes from abstract class.
#Entity("CollectionA")
public class EntityA extends BaseEntity {
//code
}
#Entity("CollectionB")
public class EntityB extends BaseEntity {
//code
}
#Entity("CollectionC")
public class EntityC extends BaseEntity {
//code
}
Then I created an visitor to reuse that in my manager to avoid using instanceOf.
public interface UpdateEntityVisitor {
void create(EntityA entityA);
void create(EntityB entityB);
void create(EntityC entityC);
}
public class UpdateEntityVisitorImpl implements UpdateEntityVisitor {
private final Factory factory;
public UpdateEntityVisitorImpl() {
factory = new FactoryImpl();
}
public UpdateEntityVisitorImpl(Factory factory) {
this.factory = factory;
}
#Override
public void create(EntityA entityA) {
factory.getEntityA().create(entityA);
}
#Override
public void create(EntityB entityB) {
factory.getEntityB().create(entityB);
}
#Override
public void create(EntityC entityC) {
factory.getEntityC().create(entityC);
}
}
And finally it's my manager class which has below method, where I would like to avoid casting down from BaseEntity to appropriate classes. There is a way to achieve that reusing above visitor class in manager ?
public void updateEntity(BaseEntity entity) {
if (checkSmth()) {
updateCollectionA((EntityA) entity);
} else {
updateCollectionB((EntityB) entity);
}
}
I found this very useful library called typeOf https://github.com/nurkiewicz/typeof but I was wondering if there is other way to make it more clear to my current team.
Does using generics work?
public <T extends BaseEntity> void updateEntity(T entity)
{
if (checkSmth())
updateCollectionA(entity);
else
updateCollectionB(entity);
}

Java generics wildcards

public interface UnivariateOperator<T> {
public TimeSeries<T> operateOn(TimeSeries<T> timeseries);
}
public class SamplingOperator<T> implements UnivariateOperator<T> {
#Override
public TimeSeries<T> sample(TimeSeries<T> timeseries) {
...
}
}
Is there a way to use wildcards so the sampling operator can work with any type? I don't really want to have to specify the type for the sampling operator...it should work with any typed timeseries.
What if you did something like this:
public class SamplingOperator<T> implements UnivariateOperator<T> {
private SamplingOperator(){
}
#Override
public TimeSeries<T> sample(TimeSeries<T> timeseries) {
...
}
public static SamplingOperator<? extends Object> getInstance() {
return new SamplingOperator<Object>();
}
}
This ensures that any instance of SamplingOperator will be able to accept any type of TimeSeries as an argument to its sample method.
There are probably better solutions out there, but this one will work.
You can't, because you need to specify the generic of UnivariateOperator. If you just want a generic method that samples TimeSeries, you will need something like
public class TimeSeriesSampler {
public static <T> TimeSeries<T> sample(TimeSeries<T> timeseries) {
...
}
}
but if you want a SamplingOperator to implements UnivariantOperator, you will need to specify the generic. If you still don't want to specify, you could use something as
public class SamplingOperator implements UnivariateOperatior<Object> {
private SamplingOperator(){
}
public <T> TimeSeries<T> sample(TimeSeries<T> timeseries) {
return null;
}
#Override
public TimeSeries<Object> operateOn(TimeSeries<Object> timeseries) {
...
}
}
but you will lose the power of the generic. Another way is
public class SamplingOperator<S> implements UnivariateOperatior<S> {
private SamplingOperator(){
}
public <T> TimeSeries<T> sample(TimeSeries<T> timeseries) {
return null;
}
#Override
public TimeSeries<S> operateOn(TimeSeries<S> timeseries) {
return timeseries;
}
}
but it "smells" bad, as the sample method gives a feeling of a class method, instead of an instance one. It's your choice what's bst to do.
implements UnivariateOperator<Object>

Class design question [optional implementation]

I was wondering how to design a system in which I have a class Super and a couple of classes that are subclasses of Super (let's say Sub1, Sub2, Sub3) and I want a class Cool. Now there are two things I want to have:
Sub1 and Sub2 can be Cool's, Sub3 can never be cool.
I must be able to have a List in which there can be Sub1's and Sub2's, if they are cool. If for example I make an object of Sub1 and it is cool I can put it in the list, if it's not it cannot be in the list.
Any suggestions? Hints?
Arne's answer kind of does what you want, but I find it overly complicated. Maybe I'm missing something? Why not just:
class Super { }
interface Cool { boolean isCool(); }
class CoolImpl extends Super implements Cool {
private boolean cool;
public CoolImpl(boolean cool) { this.cool = cool; }
public boolean isCool() { return this.cool; }
}
class Sub1 extends CoolImpl { }
class Sub2 extends CoolImpl { }
class Sub3 extends Super { }
class CoolList extends ArrayList<Cool> {
public boolean add(Cool cool) {
if (!cool.isCool()) {
return false;
}
return super.add(cool);
}
}
Maybe something like this:
class Super {}
interface Cool { boolean isCool(); }
class IsCool implements Cool {
public boolean isCool() { return true; }
}
class NotCool impolements Cool {
public boolean isCool() { return false; }
}
interface CoolSupporter {
boolean isCool();
Cool getCool();
}
class Sub1 extends Super implements CoolSupporter {
private Cool cool;
public Sub1() { this(new NotCool()); }
public Sub1(Cool cool) { this.cool = cool; }
public boolean isCool() { this.cool.isCool(); }
public Cool getCool() { return this.cool; }
}
class Sub2 extends Super implements CoolSupporter {
private Cool cool;
public Sub1() { this(new NotCool()); }
public Sub1(Cool cool) { this.cool = cool; }
public boolean isCool() { this.cool.isCool(); }
public Cool getCool() { return this.cool; }
}
class Sub3 extends Super {}
class CoolList {
private List<CoolSupporter> list = new ArrayList<CoolSupporter>();
public void add(CoolSupporter coolSupporter) {
if (coolSupporter.isCool()) {
list.add(coolSupporter);
} else {
throw new UncoolException();
}
}
}
You can create an marker interface say cool.
Let class Sub1 and Sub2 implements this interface
and before adding to the list check for instance of cool
may be this can help.
You can't have a class optionally belonging to a type in Java. Though you may subclass Sub1, with one subclass implementing an interface Cool and the other not:
class Super { }
interface Cool { }
class Sub1 extends Super { }
class Sub1Cool extends Sub1 implements Cool { }
class Sub2 extends Super { }
class Sub2Cool extends Sub2 implements Cool { }
class Sub3 extends Super { }
class CoolList extends ArrayList<Super> {
public boolean add(Super sup) {
if (!(sup instanceof Cool)) {
return false;
}
return super.add(cool);
}
}
You might also discard the Cool concept and use a visitor pattern:
class Super {
public boolean addTo(List<Super> coolList) {
if (canBeAddedToCoolList()) {
return coolList.add(this);
}
return false;
}
protected boolean canBeAddedToCoolList() {
return false;
}
}
class Sub1 extends Super {
protected boolean canBeAddedToCoolList() {
// check logic to allow/disallow addition
}
}
IMO, you need to have a overrided List (Say MyList, that overrides add()).
In add(), Check if the object you are adding is Cool, if it is so, then add it part of the list. If not then just gracefully disregard it.
Does this help?
The simplest way you can manage this is to further subclass Sub1 (CoolSub1 and NotCoolSub1) and Sub2 (CoolSub2 and NotCoolSub2).
CoolSub1 and CoolSub2 can then implement Cool ( Cool should be an interface and not a class)
You can then define
List<Cool>
which will accept implementations of Sub1 and Sub2, but only if they implement Cool.

Categories

Resources