Что хорошего в интерфейсе маркеров?

Идея или цель интерфейса маркера кажутся мне совершенно бессмысленными.

При поиске «Сериализуемого класса» в Java я неизбежно пришел к этой концепции «Маркерный интерфейс». Я понял, почему и когда его использовать - пометить/отметить класс, который предназначен для специального использования, например сериализации.

Но самое главное здесь то, что сама причина, я имею в виду идею пометить класс, чтобы указать, что мы будем использовать его для некоторого использования, но БЕЗ какого-либо метода, кажется мне совершенно абсурдной.

Если мы хотим наделить класс некоторыми специальными значениями, чтобы он мог выполнять задачи, к которым мы стремимся, я твердо верю, что он должен содержать методы, написанные для этих задач. Если он ничего не содержит внутри, чем он отличается от обычного класса? Я даже могу поместить «реализует Serializable» в любые классы, не предназначенные для сериализации.

Подводя итог, что хорошего в интерфейсе маркера?


person Rhee    schedule 03.07.2019    source источник


Ответы (4)


Интерфейса маркера действительно следует избегать.

Есть способы сделать то же самое без интерфейса маркера, как с интерфейсом маркера, и эти методы определенно следует предпочесть, поскольку интерфейс маркера считается чем-то вроде запаха кода.

В C# можно использовать атрибуты, которые можно применять к классу. Это определенно медленнее, поскольку выполнение безопасного приведения выполняется довольно быстро, но есть способы улучшить скорость за счет кэширования, например, на основе типа ввода.

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

На самом деле нет необходимости в маркерном интерфейсе.

person Eben Roux    schedule 03.07.2019

Интерфейсы маркеров изначально использовались для придания особого значения классу до того, как Java представила аннотации (в JDK 5). Например, был создан интерфейс Serializable. в JDK 1.1. С введением аннотаций лучший подход — если класс необходимо пометить и не нужны никакие дополнительные методы — использовать аннотации.

Например, вместо того, чтобы класс реализовывал интерфейс Serializable, у которого нет методов, лучше было бы создать аннотацию @Serializable и применить эту аннотацию к классу (обратите внимание, что @Serializable не настоящая аннотация, включенная в JDK).

@Serializable
public class Foo {}

Дополнительные сведения о создании и обработке аннотаций см. в разделе Создание аннотаций в Java (извините, что я написал эту статью; она включает в себя информацию, которую вам нужно знать об обработке аннотаций, не загромождая этот ответ, копируя его прямо здесь).


Другой подход заключается в том, чтобы изменить мыслительный процесс, стоящий за интерфейсом маркера, и вместо обработки классов и выполнения действий на основе их маркеров перенести логику в сам класс. Например, вместо того, чтобы искать классы с Serializable и затем выполнять логику, логику можно переместить непосредственно в интерфейс Serializable, что позволит клиентам вызывать логику сериализации непосредственно на объекте. Например:

public interface Serializable {

    public default void writeObject(ObjectOutputStream out) throws IOException {
        // ... default logic ...
    }

    public default void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        // ... default logic ...
    }

    public default void readObjectNoData() throws ObjectStreamException {
        // ... default logic ...
    }
}

Затем сериализуемый объект может быть сериализован напрямую:

public class Foo implements Serializable {}

ObjectOutputStream os = // ... some output stream
Foo foo = new Foo();
foo.writeObject(os);
person Justin Albano    schedule 03.07.2019

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

Например, когда вы объявляете, что класс реализует Serializable или Cloneable, вы разрешаете его передачу методам, которым требуются эти типы, и обещаете, что он будет придерживаться контракта этих типов с помощью принципа подстановки Лискова: https://en.wikipedia.org/wiki/Liskov_substitution_principle

В подразумеваемом контракте интерфейса есть нечто большее, чем просто методы, которые он заставляет вас переопределять.

Маркерные интерфейсы довольно редки, поскольку почти всегда лучше, чтобы функциональность, требуемая интерфейсом, реализовывалась с помощью методов интерфейса. Однако иногда, как в случае с Serializable и Cloneable, по какой-то причине это просто не соответствует шаблону. В этих случаях используется маркерный интерфейс, поскольку другие функции интерфейса остаются в силе.

person Matt Timmermans    schedule 05.07.2019

Маркерные интерфейсы используются только для идентификации типа. Кроме этого, для Marker Interface нет конкретного использования.

Например, как вы упомянули, Serializable является хорошим примером интерфейса маркера без какой-либо функции. Классы, которые реализовали Serializable и их объекты, идентифицируются для процесса сериализации с помощью JVM.

Итак, если мы хотим определить тип объекта для выполнения какой-либо конкретной операции. Мы можем создавать собственные интерфейсы маркеров и использовать их.

person siva rasiva    schedule 03.07.2019
comment
Об интерфейсе маркера обратитесь к @rhee - person siva rasiva; 07.07.2019