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