Как переопределить метод в классе, реализующем интерфейс

У меня есть интерфейс Readable и класс ReadableImpl, который его реализует.

public interface Readable {
    void doThis();
    void doThat();
} 

public class ReadableImpl implements Readable {
    public void doThis() {
        System.out.println("do this");
    }

    public void doThat() {
        System.out.println("do that");
    }
}

Что мне делать, если я хочу переопределить метод doThis()? Должен ли я реализовать Readable в другом классе?

Обновлено: я не хочу редактировать класс ReadableImpl

Что именно ты хочешь здесь делать? Вы имеете в виду два поведения для doThis() или что-то еще?

Tim Biegeleisen 29.05.2018 06:08

Вы реализовали doThis() в ReadableImpl. Если вы хотите переопределить метод, он должен быть в другом классе, расширяющем ReadableImpl. Если вы хотите переопределить в классе, вы должны правильно усвоить основы. Внутри класса есть overloading, у которого есть свои ограничения.

Ran 29.05.2018 06:09

Вы уже переопределили (я бы сказал, реализовали), не так ли?

user7 29.05.2018 06:09

@Ran Должен ли я создать еще один класс public class ReadableImpl2 extends ReadableImpl implements Readable ?

user25963 29.05.2018 06:10

В зависимости от того, что вы хотите сделать, вы можете счесть приемлемым перегрузкаdoThis в том же классе и, например, просто изменить сигнатуру метода для другого поведения.

Tim Biegeleisen 29.05.2018 06:10

@ user25963 да! нет необходимости заново реализовывать интерфейс Readable.

Ran 29.05.2018 06:11

Ваш вопрос кажется очень неясным, поскольку он не говорит, где вы хотите переопределить метод. Если вы хотите просто реализовать один метод doThis(), вам нужно сделать этот класс абстрактным, а затем создать подкласс для этого, который будет реализовывать оставшиеся абстрактные методы. Согласно приведенному вами коду, поскольку Readable является интерфейсом, а ReadableImpl реализует Readable, следовательно, он уже переопределяет метод <или вы можете сказать реализацию>.

Sagar Kharab 29.05.2018 06:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
7
235
4

Ответы 4

Ваш пример уже отменяет это! Вы можете просто переопределить doThis() в классе ReadableImpl напрямую.

Пока вы реализуете интерфейс в своем классе, вы можете переопределить любой метод в интерфейсе, просто написав точно такое же имя метода / тип возвращаемого значения / параметр в этом классе.

Технически вы реализуете (некоторые называют это переопределением) в ReadableImpl. Если вы хотите переопределить снова, это должно быть в классе, который расширяет ReadableImpl, и не нужно повторно реализовывать Readable. Просто,

public class ReadableImpl2 extends ReadableImpl {
    @override
    public void doThis() {
        System.out.println("do this overriden");
    }

}  

Я согласен с @Ran в отношении предоставленного решения, но не согласен с объяснением: "реализация" не является "преобладающий", как сказал здесь

Jul10 29.05.2018 21:08

@ HJuls2 действительно, поскольку вы можете переопределить метод абстрактным методом без реализации ...

Holger 30.05.2018 16:02

@Holger Да, то, что вы говорите, разрешено, но, честно говоря, я не вижу реального использования этого сценария ...

Jul10 30.05.2018 16:42

@ HJuls2 ну, может быть, унаследованная реализация не подходит для конкретного контракта, и подклассы должны переопределить ее другой реализацией. Иногда абстрактный метод переопределяет другой абстрактный метод только для того, чтобы иметь комментарий к документации, содержащий описание расширенного контракта.

Holger 30.05.2018 16:55

Это зависит от того, что вам нужно делать, и от необходимого вам уровня совместимости с ReadableImpl.

Вы можете создать подкласс ReadableImpl и переопределить doThis:

public class ReadableImpl2 extends ReadableImpl {
    @override
    public void doThis() {
        System.out.println("do this 2");
    }
}

Если у вас нет доступа к экземпляру, вы можете использовать прокси:

public class ReadableProxy implements Readable {
    private final Readable delegate;

    public ReadableProxy(Readable delegate) {
        this.delegate = delegate;
    }

    public void doThis() {
        System.out.println("do this proxy");
    }

    public void doThat() {
        delegate.doThat();
    }
}

Ваш вопрос

What should I do if I want to override method doThis()? Should I implement Readable in another class?

Я думаю, это не совсем понятно из-за некоторого смешения в именах операций, связанных с расширениями / реализациями. Итак, позвольте мне попытаться ответить на ваш вопрос, объяснив все вокруг на вашем примере:

public interface Readable {
    void doThis();
    void doThat();
} 

Имея такой интерфейс, вы можете implement его методы в выбранном вами классе, используя ключевое слово implements.

public class ReadableImpl implements Readable {
    public void doThis() {
        System.out.println("do this");
    }

    public void doThat() {
        System.out.println("do that");
    }
}

Теперь, если вы хотите использовать этот метод для override, единственный способ сделать это - создать новый класс, который extendsReadableImpl, потому что to override означает изменить функционал метода родительский класс в дочерний класс:

public class ReadableImplChild extends ReadableImpl{

        @Override
        public void doThis() {
            System.out.println("do this more specific way");
        }

        @Override
        public void doThat() {
            System.out.println("do that more specific way");
        }
    }

Но если вам нужен совершенно другой способ обработки этого, что ReadableImpl обрабатывает методы интерфейса Readable, вы должны создать новый класс, который будет implement для этого интерфейса введение нового функционала

 public class ReadableTotallyDifferentImpl implements Readable {
        public void doThis() {
            System.out.println("do this totally another way");
        }

        public void doThat() {
            System.out.println("do that totally another way");
        }
    }

Вы можете (я знаю, что вы не хотите, но можете) overload методом. А значит создать новую версию той же функции, которая отличается только по количеству и / или типу параметров метода.

public class ReadableImpl implements Readable {
    public void doThis() {
        System.out.println("do this");
    }

    public void doThat() {
        System.out.println("do that");
    }

    /**
     * this is funciton overloading
     */
    public void doThat(String userSpecific) {
        System.out.println("do that for:" + userSpecific);
    }
}

Согласно вашему вопросу:

What should I do if I want to override method doThis()?

Смотря как:

  1. Если вам нужен немного другой функционал (я бы сказал, более конкретный способ что-то сделать) -> вы должны создать дочерний класс и переопределить его методы
  2. Если вы хотите совершенно иную реализацию этого интерфейса, надо пойти с новым классом и реализовать его по-другому
  3. Класс Если вам действительно нужно использоватьReadableImpl, но вы хотите, чтобы этот метод работал по-другому, можно либо перегрузить это, или изменить его реализацию

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