Маркерный интерфейс или логический метод для определения возможностей объекта?
Я разрабатываю большую иерархию Java-классов, некоторые из которых имеют определенное свойство, которое мне интересно запрашивать во время выполнения (свойство определенно относится только к классам, а не к конкретным экземплярам).
Я мог бы создать абстрактный логический метод isFooBar()
что подклассы могут быть реализованы, чтобы указать, присутствует свойство или нет:
public abstract class MyBaseClass {
...
public abstract boolean isFooBar();
}
Или в качестве альтернативы я мог бы использовать интерфейс маркера FooBarProperty
и сделать instanceof
проверьте по интерфейсу:
public class MyConcreteClass extends MyBaseClass implements FooBarProperty {
...
}
Или, я думаю, вы могли бы даже использовать аннотацию, предложенную AmitD:
@FooBarAnnotation
public class MyConcreteClass extends MyBaseClass {
...
}
Каковы плюсы и минусы каждого метода и какие обычно следует отдавать предпочтение?
2 ответа
Интерфейсы маркеров наследуются в иерархии классов, поэтому они имеют ограниченные возможности (вы не можете "удалить" этот интерфейс маркеров для какого-то определенного подкласса), и я не могу рекомендовать их (Cloneable является плохим примером этого). Вопрос в том, действительно ли ваша собственность связана с классом объекта, а не с экземпляром? Если это так, аннотации лучше, потому что они не добавляют дополнительные методы в ваши API, и их проще поддерживать - вы просто добавляете / удаляете аннотацию (в случае проверки метода вы должны проверить все подклассы, переопределяют ли они это или нет).
РЕДАКТИРОВАТЬ: в вашем случае я бы задал себе вопрос: является ли мое свойство типа "является постоянным" (применяется для всех экземпляров данного класса) или "видимым" (применяется только для некоторых экземпляров)
В интерфейсах маркеров нет методов. В вашем случае ваш интерфейс имеет метод для получения свойства, и на основании этого вы должны использовать интерфейс. Вы можете просто использовать этот интерфейс для хранения конкретного экземпляра классов, который реализует ваш интерфейс и может вызывать метод, связанный со свойством.
Однако на другом конце маркера используется или отмечен и экземпляр или иерархия, так что он будет иметь право на определенные функции, такие как постоянство.