Каковы преимущества объявления объекта как интерфейса?

Возможный дубликат:
Что означает "программировать интерфейс" ?

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

Например:

Map<String, Object> someMap = new HashMap<String, Object>();

Или вы можете просто сделать

HashMap<String, Object> someMap = new HashMap<String, Object>();

и вообще не импортировать java.util.Map.

В чем преимущества объявления его через интерфейс (сначала выше) в отличие от самого класса (второй выше)?

Спасибо

Ответ 1

Если переменная не используется позже, нет никакого преимущества/недостатка. Причина, по которой вы должны использовать интерфейс, а не объект, - это обеспечить большую гибкость, но если эта переменная не используется, то нет никакой разницы в производительности.

Ответ 2

Интерфейс, такой как Map<A, B>, объявляет, что может сделать объект. С другой стороны, класс, такой как HashMap<A, B>, определяет, как объект выполняет то, что объявляет интерфейс.

Если вы объявляете переменную (или поле или что-то еще) Map<A, B>, вы заявляете, что ваш код зависит только от контракта, определенного этим интерфейсом, он не зависит от специфики реализации.

Если вы объявите его HashMap<A, B>, следует понимать, что вам нужна эта конкретная версия карты (по какой-либо причине), и ее нельзя заменить для чего-то еще.

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

Ответ 4

Если вы используете Map<String, Object> someMap, вы разрабатываете интерфейс, а не реализацию. Таким образом, вы можете легко переключаться между другими реализациями.

Итак, ваш Map может указывать на HashMap, LinkedHashMap или любой другой объект, который является подклассом Map.

Итак, если у вас есть: -

Map<String, Integer> someMap = new HashMap<>();

Вы можете изменить реализацию позже (если хотите), чтобы указать на LinkedHashMap: -

someMap = new LinkedHashMap<>();

Если вы используете HashMap в LHS, вы можете указать только объект типа HashMap..

Но, как таковой, нет никакой разницы в производительности. Но всегда рекомендуется design использовать interface, а не implementation..

Ответ 5

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

Пример:

interface Printer {
    public void print(String text);
}

class FilePrinter implements Printer {
    public void print(String text) {
       //append the text to a file
    }
}

class ScreenPrinter implements Printer {
    public void print(String text) {
       //write the text on the screen
    }
}

class SomeClass {
    public printSomething(Printer myPrinter) {
        myPrinter.print("Hello");
    }
}

Если вы вызываете SomeClass.printSomething(...), не имеет значения, передаете ли вы экземпляр FilePrinter или ScreenPrinter, потому что метод просто не волнует. Он знает, что объект реализует интерфейс Printer, а также реализует его методы.

Другим важным моментом в интерфейсах является то, что класс может реализовывать несколько интерфейсов.