Почему класс 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. Дизайнеры решили сохранить обратную совместимость уже существующего интерфейса. В противном случае многим разработчикам пришлось бы менять свой код.
-
Логический: методы, о которых вы говорите, не требуют внутренних знаний в реализации списка и могут быть реализованы через ЛЮБЫЕ коллекции, реализующие его.