Сохранение переменной как подкласса (интерфейса)

Я делаю расширение 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.

Есть ли способ сохранить подкласс в переменной типа его суперкласса без приведения к нему? Я не хочу иметь фактические переменные для каждого типа слушателя.

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

daniu 18.01.2019 17:17

OnCommunicationFailedListener не должен быть вашим суперклассом, извлеките методы, общие для FailedListener и AchievedListener, в более общий Listener. Но, может быть, вам стоит почитать немного больше о наследовании

DGK 18.01.2019 17:20

@Laurens, я говорю, что у меня будет другой слушатель, который также реализует «неудачный», поэтому, когда результат операции в классе будет нулевым, я вызову listener.onCommunicationFailed(), независимо от того, какой тип слушатель.

Iaka Noe 18.01.2019 17:23

Я не могу понять, чего вы пытаетесь достичь или что вы для этого делаете. Не могли бы вы переформулировать некоторые вопросы, чтобы сделать их более ясными и добавить больше кода? Спасибо

Software Engineer 18.01.2019 17:25

@EngineerDollery редактирует...

Iaka Noe 18.01.2019 17:28
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
53
0

Другие вопросы по теме