Со всем уважением не согласен с большинством вышеприведенных плакатов (извините! Модифицируйте меня, если хотите :-))
Во-первых, ответ «только один суперкласс» неубедителен. Любой, кто дал бы мне такой ответ в интервью, быстро бы возразил: «C++ существовал до того, как Java, а C++ имел несколько суперклассов. Как вы думаете, почему Джеймс Гослинг разрешил только один суперкласс для Java?»
Поймите философию, стоящую за вашим ответом, иначе вас поджарят (по крайней мере, если я возьму у вас интервью).
Во-вторых, интерфейсы имеют множество преимуществ перед абстрактными классами, особенно при разработке интерфейсов. Самый большой из них — отсутствие определенной структуры класса, навязанной вызывающему методу. Нет ничего хуже, чем пытаться использовать вызов метода, который требует определенной структуры класса. Это больно и неловко. Используя интерфейс, методу можно передать все с минимальными ожиданиями.
Пример:
public void foo(Hashtable bar);
vs.
public void foo(Map bar);
В первом случае вызывающая сторона всегда будет брать существующую структуру данных и помещать ее в новую хеш-таблицу.
В-третьих, интерфейсы позволяют общедоступным методам в конкретных реализациях классов быть «приватными». Если метод не объявлен в интерфейсе, то этот метод не может быть использован (или использован не по назначению) классами, которые не имеют никакого отношения к использованию этого метода. Что подводит меня к пункту 4....
В-четвертых, интерфейсы представляют собой минимальный контракт между реализующим классом и вызывающей стороной. Этот минимальный контракт точно определяет, как будет использоваться конкретный разработчик, и не более того. Вызывающему классу не разрешается использовать любой другой метод, не указанный в «контракте» интерфейса. Используемое имя интерфейса также влияет на ожидания разработчика относительно того, как он должен использовать объект. Если разработчик прошел
public interface FragmentVisitor {
public void visit(Node node);
}
Разработчик знает, что единственный метод, который он может вызвать, — это метод посещения. Они не отвлекаются на яркие блестящие методы в конкретном классе, с которыми им не следует связываться.
Наконец, абстрактные классы имеют множество методов, которые на самом деле существуют только для использования подклассами. Таким образом, абстрактные классы, как правило, выглядят для внешнего разработчика как беспорядок, нет никаких указаний о том, какие методы предназначены для использования внешним кодом.
Да, конечно, некоторые такие методы можно сделать защищенными. Однако, к сожалению, защищенные методы также видны другим классам в том же пакете. И если метод абстрактного класса реализует интерфейс, метод должен быть общедоступным.
Однако, используя интерфейсы, все эти внутренности, которые болтаются при взгляде на абстрактный суперкласс или конкретный класс, надежно спрятаны.
Да, я знаю, что, конечно, разработчик может использовать некоторые «специальные» знания, чтобы привести объект к другому более широкому интерфейсу или к самому конкретному классу. Но такой бросок нарушает ожидаемый контракт, и разработчика следует шлепнуть лососем.
15.03.2009