È buona norma usare Object quando un metodo può accettare più di un tipo di oggetto?

3
public class TaskA implements Runnable {
....
}
public class TaskB implements Runnable {
....
}

Ho due classi eseguibili come TaskA, TaskB. Voglio avere un TaskManager per eseguire queste due attività e avere la possibilità di aggiungere più attività in futuro. Quindi ho il TaskManager come segue:

public class TaskManager {
    private ThreadPoolExecutor threadPool;
    private Object task;

    public TaskManager(TaskA task) {
        this.task = task;
    }
    public TaskManager(TaskB task) {
        this.task = task;
    }

    public void startThreadPool() {
        threadPool = new ThreadPoolExecutor(...);
        threadPool.execute((Runnable) task);
    }
}

Vorrei sapere se è una buona pratica? Se no, qualcuno ha qualche suggerimento? dovremmo usare il consumatore o così per implementare questo?

    
posta c2340878 07.03.2017 - 02:32
fonte

2 risposte

9

Dal momento che sembra che tu usi solo l'attività come Runnable internamente, usa Runnable invece di Object. Cambia la tua terza linea in:

private final Runnable task;

Semplice, ti salva un cast più tardi. E io considero rinominandolo da "compito" a "eseguibile" per chiarezza, se questo ha più senso.

    
risposta data 07.03.2017 - 05:03
fonte
2

TLDR:

Utilizza un solo costruttore che accetta Runnable e un membro di tipo Runnable .

Risposta lunga:

Se davvero, ha davvero bisogno di due costruttori diversi, , uno che riceve TaskA e uno che riceve TaskB , (un possibile motivo è che TaskManager chiama metodi che sono particolari a TaskA o TaskB ) quindi hai due opzioni:

  1. hanno due membri, private TaskA taskA e private TaskB taskB
  2. hai solo un membro private Runnable task , poiché Runnable è l'antenato comune di TaskA e TaskB

D'altra parte, se non hai davvero bisogno di un costruttore per ogni tipo di attività, puoi avere solo un costruttore public TaskManager(Runnable task) e solo un membro di tipo Runnable come in opzione 2 precedentemente indicata.

Tutto dipende dalla necessità o meno di chiamare metodi che sono particolari a TaskA o TaskB . Se TaskManager si preoccupa solo del Runnable contratto allora non c'è bisogno di due costruttori, per non parlare di dover lanciare un Object a Runnable per eseguirlo.

Infine, se TaskManager ha davvero bisogno di qualcosa dai compiti accanto alla funzionalità Runnable , quindi crea un RunnableTask come questo:

public interface RunnableTask extends Runnable {
    public int getThis();
    public int getThat();
}

public class TaskA implements RunnableTask { ... }
public class TaskB implements RunnableTask { ... }

public class TaskManager {
    ...
    private RunnableTask task;

    public TaskManager(RunnableTask task) {
        this.task = task;
    }

    public void startThreadPool() {
        threadPool = new ThreadPoolExecutor(...);
        threadPool.execute(task);
        // do somewthing with task.getThis();
        // do somewthing with task.getThat();
    }
    ...
}
    
risposta data 07.03.2017 - 15:33
fonte

Leggi altre domande sui tag