Когда я должен вернуть интерфейс и когда конкретный класс? - PullRequest
21 голосов
/ 31 мая 2009

при программировании на Java я практически всегда, просто по привычке, пишу что-то вроде этого:

public List<String> foo() {
    return new ArrayList<String>();
}

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

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

List bar = foo();
List myList = bar instanceof LinkedList ? new ArrayList(bar) : bar;

но это только кажется ужасным, и мои коллеги, вероятно, линчуют меня в столовой. И это справедливо.

Что вы, ребята, думаете? Каковы ваши рекомендации, когда вы стремитесь к абстрактному решению и когда вы раскрываете детали своей реализации для потенциального повышения производительности?

Ответы [ 12 ]

1 голос
/ 31 мая 2009

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

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

Для работы с интерфейсами вы должны создавать их так:

IParser parser = new Parser();

Теперь IParser будет вашим интерфейсом, а Parser - вашей реализацией. Теперь, когда вы работаете с объектом парсера сверху, вы будете работать с интерфейсом (IParser), который, в свою очередь, будет работать против вашей реализации (Parser).

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

0 голосов
/ 31 мая 2009

Вы обнаружите (или нашли), что когда вы возвращаете интерфейсы, они проникают через ваш код. например вы возвращаете интерфейс из метода A, и у вас есть , чтобы затем передать интерфейс в метод B.

То, что вы делаете, это программирование по контракту, хотя и ограниченным образом.

Это дает вам огромные возможности для изменения реализаций под прикрытием (при условии, что эти новые объекты соответствуют существующим контрактам / ожидаемым действиям).

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

...