Java Generic Interfaces with multiple implementations












4















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.





  1. Why do I need to cast the return value like this



    return (TaskService) taskAService;



  2. 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.










share|improve this question

























  • this code doesn't seem to compile

    – Andrew Tobilko
    Nov 13 '18 at 9:14






  • 1





    Don't use == with Strings: use a switch statement or .equals()

    – Maurice Perry
    Nov 16 '18 at 6:03











  • @AndrewTobilko I just wrote pseudo code to be able to ask my question.

    – Muneer Y
    Nov 16 '18 at 6:12











  • @MauricePerry I update my code basing on your comment.

    – Muneer Y
    Nov 16 '18 at 6:12
















4















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.





  1. Why do I need to cast the return value like this



    return (TaskService) taskAService;



  2. 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.










share|improve this question

























  • this code doesn't seem to compile

    – Andrew Tobilko
    Nov 13 '18 at 9:14






  • 1





    Don't use == with Strings: use a switch statement or .equals()

    – Maurice Perry
    Nov 16 '18 at 6:03











  • @AndrewTobilko I just wrote pseudo code to be able to ask my question.

    – Muneer Y
    Nov 16 '18 at 6:12











  • @MauricePerry I update my code basing on your comment.

    – Muneer Y
    Nov 16 '18 at 6:12














4












4








4


1






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.





  1. Why do I need to cast the return value like this



    return (TaskService) taskAService;



  2. 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.










share|improve this question
















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.





  1. Why do I need to cast the return value like this



    return (TaskService) taskAService;



  2. 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.







java generics interface






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 6:22







Muneer Y

















asked Nov 13 '18 at 8:08









Muneer YMuneer Y

213




213













  • this code doesn't seem to compile

    – Andrew Tobilko
    Nov 13 '18 at 9:14






  • 1





    Don't use == with Strings: use a switch statement or .equals()

    – Maurice Perry
    Nov 16 '18 at 6:03











  • @AndrewTobilko I just wrote pseudo code to be able to ask my question.

    – Muneer Y
    Nov 16 '18 at 6:12











  • @MauricePerry I update my code basing on your comment.

    – Muneer Y
    Nov 16 '18 at 6:12



















  • this code doesn't seem to compile

    – Andrew Tobilko
    Nov 13 '18 at 9:14






  • 1





    Don't use == with Strings: use a switch statement or .equals()

    – Maurice Perry
    Nov 16 '18 at 6:03











  • @AndrewTobilko I just wrote pseudo code to be able to ask my question.

    – Muneer Y
    Nov 16 '18 at 6:12











  • @MauricePerry I update my code basing on your comment.

    – Muneer Y
    Nov 16 '18 at 6:12

















this code doesn't seem to compile

– Andrew Tobilko
Nov 13 '18 at 9:14





this code doesn't seem to compile

– Andrew Tobilko
Nov 13 '18 at 9:14




1




1





Don't use == with Strings: use a switch statement or .equals()

– Maurice Perry
Nov 16 '18 at 6:03





Don't use == with Strings: use a switch statement or .equals()

– Maurice Perry
Nov 16 '18 at 6:03













@AndrewTobilko I just wrote pseudo code to be able to ask my question.

– Muneer Y
Nov 16 '18 at 6:12





@AndrewTobilko I just wrote pseudo code to be able to ask my question.

– Muneer Y
Nov 16 '18 at 6:12













@MauricePerry I update my code basing on your comment.

– Muneer Y
Nov 16 '18 at 6:12





@MauricePerry I update my code basing on your comment.

– Muneer Y
Nov 16 '18 at 6:12












2 Answers
2






active

oldest

votes


















1














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);
}
}





share|improve this answer


























  • I doubt if it's OK that a task would know about its manager

    – Andrew Tobilko
    Nov 13 '18 at 8:39











  • @AndrewTobilko Edited it, the logic can be only inside the Base Class. That way the child Tasks will never have to know about the manager. But Yes, BaseTask will still know about it. That should still be fine as Manager class here is just a friend or helper type of class to keep track of the different tasks which are running.

    – Bandi Kishore
    Nov 13 '18 at 8:49











  • Children still would require a TaskServiceManager

    – Andrew Tobilko
    Nov 13 '18 at 8:56











  • No change, the same way a Service class was instantiated. Since its spring, you'll only have to annotate it with @Service (Added it to the answer). Basically a SIngleton class and inject the Manager class into BaseTask. If using Spring, we could directly Inject the Manager into Base class without having to send it from child. But wouldn't work if there is no DI framework. Any suggestions on how to make it better?

    – Bandi Kishore
    Nov 13 '18 at 8:56













  • Tasks aren't beans, they are extracted from an order

    – Andrew Tobilko
    Nov 13 '18 at 8:57





















1














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);





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53276456%2fjava-generic-interfaces-with-multiple-implementations%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    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);
    }
    }





    share|improve this answer


























    • I doubt if it's OK that a task would know about its manager

      – Andrew Tobilko
      Nov 13 '18 at 8:39











    • @AndrewTobilko Edited it, the logic can be only inside the Base Class. That way the child Tasks will never have to know about the manager. But Yes, BaseTask will still know about it. That should still be fine as Manager class here is just a friend or helper type of class to keep track of the different tasks which are running.

      – Bandi Kishore
      Nov 13 '18 at 8:49











    • Children still would require a TaskServiceManager

      – Andrew Tobilko
      Nov 13 '18 at 8:56











    • No change, the same way a Service class was instantiated. Since its spring, you'll only have to annotate it with @Service (Added it to the answer). Basically a SIngleton class and inject the Manager class into BaseTask. If using Spring, we could directly Inject the Manager into Base class without having to send it from child. But wouldn't work if there is no DI framework. Any suggestions on how to make it better?

      – Bandi Kishore
      Nov 13 '18 at 8:56













    • Tasks aren't beans, they are extracted from an order

      – Andrew Tobilko
      Nov 13 '18 at 8:57


















    1














    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);
    }
    }





    share|improve this answer


























    • I doubt if it's OK that a task would know about its manager

      – Andrew Tobilko
      Nov 13 '18 at 8:39











    • @AndrewTobilko Edited it, the logic can be only inside the Base Class. That way the child Tasks will never have to know about the manager. But Yes, BaseTask will still know about it. That should still be fine as Manager class here is just a friend or helper type of class to keep track of the different tasks which are running.

      – Bandi Kishore
      Nov 13 '18 at 8:49











    • Children still would require a TaskServiceManager

      – Andrew Tobilko
      Nov 13 '18 at 8:56











    • No change, the same way a Service class was instantiated. Since its spring, you'll only have to annotate it with @Service (Added it to the answer). Basically a SIngleton class and inject the Manager class into BaseTask. If using Spring, we could directly Inject the Manager into Base class without having to send it from child. But wouldn't work if there is no DI framework. Any suggestions on how to make it better?

      – Bandi Kishore
      Nov 13 '18 at 8:56













    • Tasks aren't beans, they are extracted from an order

      – Andrew Tobilko
      Nov 13 '18 at 8:57
















    1












    1








    1







    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);
    }
    }





    share|improve this answer















    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);
    }
    }






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 13 '18 at 9:13

























    answered Nov 13 '18 at 8:30









    Bandi KishoreBandi Kishore

    3,5311832




    3,5311832













    • I doubt if it's OK that a task would know about its manager

      – Andrew Tobilko
      Nov 13 '18 at 8:39











    • @AndrewTobilko Edited it, the logic can be only inside the Base Class. That way the child Tasks will never have to know about the manager. But Yes, BaseTask will still know about it. That should still be fine as Manager class here is just a friend or helper type of class to keep track of the different tasks which are running.

      – Bandi Kishore
      Nov 13 '18 at 8:49











    • Children still would require a TaskServiceManager

      – Andrew Tobilko
      Nov 13 '18 at 8:56











    • No change, the same way a Service class was instantiated. Since its spring, you'll only have to annotate it with @Service (Added it to the answer). Basically a SIngleton class and inject the Manager class into BaseTask. If using Spring, we could directly Inject the Manager into Base class without having to send it from child. But wouldn't work if there is no DI framework. Any suggestions on how to make it better?

      – Bandi Kishore
      Nov 13 '18 at 8:56













    • Tasks aren't beans, they are extracted from an order

      – Andrew Tobilko
      Nov 13 '18 at 8:57





















    • I doubt if it's OK that a task would know about its manager

      – Andrew Tobilko
      Nov 13 '18 at 8:39











    • @AndrewTobilko Edited it, the logic can be only inside the Base Class. That way the child Tasks will never have to know about the manager. But Yes, BaseTask will still know about it. That should still be fine as Manager class here is just a friend or helper type of class to keep track of the different tasks which are running.

      – Bandi Kishore
      Nov 13 '18 at 8:49











    • Children still would require a TaskServiceManager

      – Andrew Tobilko
      Nov 13 '18 at 8:56











    • No change, the same way a Service class was instantiated. Since its spring, you'll only have to annotate it with @Service (Added it to the answer). Basically a SIngleton class and inject the Manager class into BaseTask. If using Spring, we could directly Inject the Manager into Base class without having to send it from child. But wouldn't work if there is no DI framework. Any suggestions on how to make it better?

      – Bandi Kishore
      Nov 13 '18 at 8:56













    • Tasks aren't beans, they are extracted from an order

      – Andrew Tobilko
      Nov 13 '18 at 8:57



















    I doubt if it's OK that a task would know about its manager

    – Andrew Tobilko
    Nov 13 '18 at 8:39





    I doubt if it's OK that a task would know about its manager

    – Andrew Tobilko
    Nov 13 '18 at 8:39













    @AndrewTobilko Edited it, the logic can be only inside the Base Class. That way the child Tasks will never have to know about the manager. But Yes, BaseTask will still know about it. That should still be fine as Manager class here is just a friend or helper type of class to keep track of the different tasks which are running.

    – Bandi Kishore
    Nov 13 '18 at 8:49





    @AndrewTobilko Edited it, the logic can be only inside the Base Class. That way the child Tasks will never have to know about the manager. But Yes, BaseTask will still know about it. That should still be fine as Manager class here is just a friend or helper type of class to keep track of the different tasks which are running.

    – Bandi Kishore
    Nov 13 '18 at 8:49













    Children still would require a TaskServiceManager

    – Andrew Tobilko
    Nov 13 '18 at 8:56





    Children still would require a TaskServiceManager

    – Andrew Tobilko
    Nov 13 '18 at 8:56













    No change, the same way a Service class was instantiated. Since its spring, you'll only have to annotate it with @Service (Added it to the answer). Basically a SIngleton class and inject the Manager class into BaseTask. If using Spring, we could directly Inject the Manager into Base class without having to send it from child. But wouldn't work if there is no DI framework. Any suggestions on how to make it better?

    – Bandi Kishore
    Nov 13 '18 at 8:56







    No change, the same way a Service class was instantiated. Since its spring, you'll only have to annotate it with @Service (Added it to the answer). Basically a SIngleton class and inject the Manager class into BaseTask. If using Spring, we could directly Inject the Manager into Base class without having to send it from child. But wouldn't work if there is no DI framework. Any suggestions on how to make it better?

    – Bandi Kishore
    Nov 13 '18 at 8:56















    Tasks aren't beans, they are extracted from an order

    – Andrew Tobilko
    Nov 13 '18 at 8:57







    Tasks aren't beans, they are extracted from an order

    – Andrew Tobilko
    Nov 13 '18 at 8:57















    1














    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);





    share|improve this answer






























      1














      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);





      share|improve this answer




























        1












        1








        1







        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);





        share|improve this answer















        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);






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 16 '18 at 6:37

























        answered Nov 16 '18 at 6:23









        Maurice PerryMaurice Perry

        5,5562516




        5,5562516






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53276456%2fjava-generic-interfaces-with-multiple-implementations%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            List item for chat from Array inside array React Native

            Thiostrepton

            Caerphilly