Является ли интерфейс как ярлыки плохой практикой в ​​Java OO?

StackOverflow https://stackoverflow.com/questions/1436674

  •  08-07-2019
  •  | 
  •  

Вопрос

Во время синтаксического анализа некоторых XML-файлов я сталкиваюсь с ситуацией, когда мне приходится использовать интерфейс в качестве меток для определения того, что определенные теги принадлежат определенной категории, например, я создал интерфейс Tag для определить, что эти классы используются для представления тегов xml, а ContainableTag указать, что определенные теги могут быть одним из дочерних тегов некоторых тегов.

Затем я наткнулся на эту страницу: http://xahlee.org/java-a -day / interface.html (см. сеанс " Интерфейс как метки "). Это говорит:

  

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

Так что интерфейс как ярлыки обязательно плохая практика? Как программист Java, у нас есть другие альтернативы?

Это было полезно?

Решение

Интерфейсы как маркеры были в значительной степени заменены механизмом аннотации в Java 5 или более поздней версии. Они позволяют добавлять произвольные метаданные. Если ваши интерфейсы пусты и служат только в качестве маркеров классов, вам следует вместо этого использовать аннотации.

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

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

Что касается упомянутой вами статьи, я не вижу смысла в том, чтобы утверждать, что если класс синтаксически / структурно "выполняет" интерфейс, этот интерфейс может / должен применяться автоматически к классу («Любой класс может объявить его [RandomAccess] как интерфейс ...»). Это обратное мышление, по моему мнению.

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

Также обратите внимание, что этот тупиковый аргумент о том, что пустой интерфейс всегда применим, также может применяться к аннотациям.

Аннотации не обязательно то, что вы хотите. Интерфейсы тегов - это способ вписать свойство типа в сам тип. Например, если вы собираетесь начать писать код, похожий на этот:

@interface ContainableTag{}

@ContainableTag public class Foo {}

// ... elsewhere...

/**
 * Adds obj as a child element.
 * @throws IllegalArgumentException if obj is not tagged with 
 *         the ContainableTag annotation.
 */
public void addElement(Object obj){
    if (!obj.getClass().isAnnotationPresent(ContainableTag.class))
        throw new IllegalArgumentException("obj is not a ContainableTag");
    // add the containable tag as an element
}

Тогда подумайте, действительно ли вы думаете, что это выглядит лучше:

interface ContainableTag {}

public class Foo implements ContainableTag {}

// ... elsewhere...

public void addElement(ContainableTag ct){
    // add the containable tag as an element
}

Конечно, интерфейс тегов не предоставляет никакой информации о том, какое поведение обеспечивает сам тип, но он делает , чтобы другие типы могли применять это свойство без поведения. Я, конечно, был бы избавлен от множества досадных ошибок, если бы ObjectOutputStream имел метод writeObject (Serializable) , а не writeObject (Object) .

Изменить. У меня есть немаловажная поддержка здесь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top