Я делаю расширение AsyncTask, которое взаимодействует со службой, используя разные действия, и возвращает разные типы результатов в зависимости от используемого действия. У каждого действия есть прослушиватель, состоящий из интерфейсов, расширяющих один интерфейс с именем OnCommunicationFailedListener. Дело в том, что я хочу иметь только одну переменную для сохранения прослушивателя, типа OnCommunicationFailedListener, и дать пользователю возможность сохранять все «подинтерфейсы» в этой переменной. Они могут сохранить их просто как есть, но я не могу вызывать методы, которые вводит «подинтерфейс».
class CommunicationTask extends AsyncTask<Void, Void, String> {
private Action action;
private OnCommunicationFailedListener listener;
enum Action {
LOGIN,
LOGOUT,
SEARCH
}
interface OnCommunicationFailedListener {
void onCommunicationFailed();
}
interface OnLoginAchievedListener extends OnCommunicationFailedListener {
void onLoggedIn(String result);
void onLoginError(String error);
}
interface OnLogoutAchievedListener extends OnCommunicationFailedListener {
void onLoggedOut(String result);
void onLogoutError(String error);
}
interface OnSearchAchievedListener extends OnCommunicationFailedListener {
void onSearchAchieved(String[] results);
}
@Override protected String doInBackground(Void... voids){
try {
// Try to communicate with a query, resulting in some result.
return result;
} catch(IOException e) {
e.printStackTrace();
}
return null;
}
@Override protected void onPostExecute(String result){
super.onPostExecute(result);
if (result == null) {
listener.onCommunicationFailed();
return;
}
// ALL OF THESE GIVE ERRORS, SINCE THE METHODS DO NOT EXIST ANYMORE
switch(action){
case LOGIN:
if (<check if result is ok>){
listener.onLoggedIn(result);
} else listener.onLoginError(<some error>);
break;
case LOGOUT:
if (<check if result is ok>){
listener.onLoggedOut(result);
} else listener.onLogoutError(<some error>);
break;
case SEARCH:
String[] results = <process result>;
listener.onSearchAchieved(results);
break;
}
}
void login(String user, String password, OnLoginAchievedListener listener){
this.listener = listener;
action = Action.LOGIN;
//Build the query...
execute();
}
void logout(OnLogoutAchievedListener listener){
this.listener = listener;
action = Action.LOGOUT;
//Build the query...
execute();
}
void search(String query, OnSearchAchievedListener listener){
this.listener = listener;
action = Action.SEARCH;
//Build the query...
execute();
}
}
Идея состоит в том, что другой класс вызывает методы login(), logout() или search() и дает им прослушиватель типа действия. Когда связь завершается и результат получен, вызываются методы слушателя действия (в моем коде это происходит в операторе switch).
Дело в том, что эти методы нельзя вызывать, так как переданный слушатель был приведен к OnCommunicationFailedListener.
Есть ли способ сохранить подкласс в переменной типа его суперкласса без приведения к нему? Я не хочу иметь фактические переменные для каждого типа слушателя.
OnCommunicationFailedListener не должен быть вашим суперклассом, извлеките методы, общие для FailedListener и AchievedListener, в более общий Listener. Но, может быть, вам стоит почитать немного больше о наследовании
@Laurens, я говорю, что у меня будет другой слушатель, который также реализует «неудачный», поэтому, когда результат операции в классе будет нулевым, я вызову listener.onCommunicationFailed(), независимо от того, какой тип слушатель.
Я не могу понять, чего вы пытаетесь достичь или что вы для этого делаете. Не могли бы вы переформулировать некоторые вопросы, чтобы сделать их более ясными и добавить больше кода? Спасибо
@EngineerDollery редактирует...




Вы не показываете достаточно кода, чтобы дать точное указание, что не так с вашим дизайном, но если вы находитесь в положении, когда вы хотите вызвать подкласс (например, обработчик входа в систему), вы определенно должны поддерживать этот подкласс интерфейса а не общий родительский.