Почему класс Collections содержит автономные (статические) методы, а не добавляется в интерфейс List?

Для всех методов Collections, которые принимают List в качестве первого аргумента, почему эти методы не являются просто частью интерфейса List?

Моя интуиция: задан объект List, этот объект должен "знать", как выполнять на себе операции, такие как rotate(), shuffle() или reverse(). Но вместо этого, как программист Java, я должен рассмотреть как методы в интерфейсе List, так и статические методы "там" в классе Collections, чтобы убедиться, что я использую каноническое решение.

Почему некоторые методы были помещены как статические автономные методы в класс Collections, а не добавлены в интерфейс List (и предположительно таким образом реализованы каким-то существующим или потенциальным базовым классом)?

Я пытаюсь лучше понять дизайнерские решения, лежащие в основе структуры коллекций Java.

Есть ли какой-то убедительный принцип дизайна OO здесь, который я пропускаю? Или это различие сделано просто для некоторых практических соображений производительности?

Ответы

Ответ 1

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

Эффективно, java.util.Collections похож на .NET Enumerable class - полный методов общего назначения, которые могут работать в любой коллекции, чтобы они могли совместно использовать одну реализацию и избегать дублирования.

Ответ 2

Рациональные методы интерфейса списка

  • Интерфейс List является очень важной частью среды выполнения Java и уже немного обременителен, чтобы полностью реализовать всех участников при развертывании собственных реализаций списка. Таким образом, добавление дополнительных методов, которые напрямую не связаны с определением списка, немного постороннее. Если вам нужны эти методы в реализации List, почему бы не подклассифицировать интерфейс, а затем потребовать их?
  • Если вы придете, скажем в версии 1.3 и добавьте функциональность в интерфейс List, добавив новые методы утилиты, вы сломаете все прошлые разработчики интерфейса.
  • С точки зрения управления с помощью домена методы утилиты в коллекциях не являются частью обычного домена списка.
  • Что касается принципов дизайна OO, я думаю, что было бы важно провести различие между дизайном OO приложения и дизайном OO языка.

Авторы Java могут поступить совсем по-другому, поскольку они имеют задним числом и перспективу многолетнего использования API. Тем не менее, интерфейс С# IList очень похож на Java и авторы С# имели перспективу.

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

Здесь есть два объяснения:

  • Исторический: класс Collections был создан после интерфейса List. Дизайнеры решили сохранить обратную совместимость уже существующего интерфейса. В противном случае многим разработчикам пришлось бы менять свой код.

  • Логический: методы, о которых вы говорите, не требуют внутренних знаний в реализации списка и могут быть реализованы через ЛЮБЫЕ коллекции, реализующие его.