Просматривая Java Collections Framework, я заметил, что довольно много интерфейсов имеют комментарий (optional operation)
. Эти методы позволяют реализовать классы, UnsupportedOperationException
если они просто не хотят реализовывать этот метод.
Примером этого является addAll
метод в Set Interface
.
Теперь, как указано в этой серии вопросов, интерфейсы являются определяющим контрактом для того, что может ожидать использование.
Интерфейсы важны, потому что они отделяют то, что делает класс, от того, как он это делает. Контракт, определяющий, чего может ожидать клиент, дает разработчику право свободно реализовывать его любым удобным для него способом, пока он поддерживает контракт.
и
Интерфейс - это описание действий, которые объект может выполнять ... например, когда вы нажимаете выключатель света, свет включается, вам все равно, как, просто так и происходит. В объектно-ориентированном программировании интерфейс - это описание всех функций, которые должен иметь объект, чтобы быть «Х».
и
Я думаю, что подход на основе интерфейса значительно лучше. После этого вы можете красиво смоделировать свои зависимости, и все в основном будет менее тесно связано.
Интерфейс + расширение (mixin) против базового класса
Учитывая, что цель интерфейсов состоит в том, чтобы определить контракт и сделать ваши зависимости слабо связанными, разве некоторые методы не бросают своего UnsupportedOperationException
рода поражение цели? Это значит, что я больше не могу пройти Set
и просто использовать addAll
. Скорее, я должен знать, какую реализацию Set
я прошел, чтобы я мог знать, могу ли я использовать addAll
или нет. Это кажется довольно бесполезным для меня.
Так в чем смысл UnsupportedOperationException
? Это просто компенсирует устаревший код, и им нужно очистить свои интерфейсы? Или у меня есть более чувственная цель, которую мне не хватает?
источник
addAll
вHashSet
. Он сдвинуто реализации по умолчанию , вAbstractCollection
котором большинство , конечно же , не бросатьUnsupportedOperationException
.src.zip
ним, он прекрасно работает. Это помогает точно знать, какой код JRE иногда выполняет, и не откладывать на JavaDoc, который может быть немного многословным.Ответы:
Посмотрите на следующие интерфейсы:
Все эти интерфейсы объявляют мутирующие методы как необязательные. Это неявно документирует тот факт, что класс Collections может возвращать реализации тех интерфейсов, которые являются неизменяемыми: то есть эти дополнительные операции мутации гарантированно завершатся неудачно. Однако в соответствии с контрактом в JavaDoc все реализации этих интерфейсов должны разрешать операции чтения. Это включает в себя «нормальные» реализации, такие как
HashSet
иLinkedList
неизменные оболочки вCollections
.Контраст с интерфейсами очереди:
Эти интерфейсы не определяют никаких дополнительных операций: очередь, по определению, предназначена для предложения и опроса элементов способом FIFO. Неизменная очередь примерно так же полезна, как и машина без колес.
Одна распространенная идея, которая часто возникает, - это иметь иерархию наследования, которая имеет как изменяемые, так и неизменные объекты. Однако все они имеют недостатки. Сложность мутит воду, фактически не решая проблему.
Гипотетический
Set
может иметь операции чтения, а подынтерфейсMutableSet
может иметь операции записи. Лисков говорит нам, чтоMutableSet
затем можно передать все, что нужноSet
. Сначала это звучит нормально, но рассмотрим метод, который ожидает, что базовый набор не будет изменен во время чтения: два потока могут использовать один и тот же набор и нарушать неизменяемый инвариант набора. Это может вызвать проблему, например, если метод читает элемент из набора дважды, и это происходит в первый раз, но не во второй раз.Set
не может иметь прямых реализаций, вместо этого иметьMutableSet
иImmutableSet
как подынтерфейсы, которые затем используются для реализации классов. Это имеет ту же проблему, что и выше: в какой-то момент в иерархии интерфейс имеет конфликтующие инварианты. Один говорит, что этот набор должен быть изменяемым, а другой говорит, что этот набор не может измениться.Могут быть две совершенно разные иерархии для изменяемых и неизменяемых структур данных. Это добавляет тонну дополнительной сложности, что в итоге приводит к очень небольшому выигрышу. Это также имеет специфическую слабость методов, которые не заботятся об изменчивости (например, я просто хочу перебрать список), теперь должны поддерживать два отдельных интерфейса. Поскольку Java имеет статическую типизацию, это означает дополнительные методы для обработки обеих иерархий интерфейса.
Мы могли бы иметь единственный интерфейс и позволить реализациям генерировать исключения, если метод не применим к нему. Это путь, по которому пошла Java, и он имеет смысл. Количество интерфейсов сведено к минимуму, и нет никаких инвариантов изменчивости, потому что документированный интерфейс не дает никаких гарантий относительно изменчивости в любом случае . Если требуется неизменный инвариант, используйте обертки в
Collections
. Если метод не должен изменять коллекцию, просто не меняйте его. Недостатком является то, что метод не может гарантировать, что коллекция не изменится в другом потоке, если ему будет предоставлена коллекция извне, но в любом случае это касается вызывающего метода (или его вызывающего метода).Связанное чтение: Почему Java 8 не включает неизменяемые коллекции?
источник
MutableCollection
?Это в основном ЯГНИ. Все конкретные коллекции в стандартной библиотеке являются изменяемыми, реализуя или наследуя необязательные операции. Они не заботятся о неизменяемых коллекциях общего назначения, равно как и подавляющее большинство разработчиков Java. Они не собираются создавать целую иерархию интерфейса только для неизменяемых коллекций, а затем не включают никаких реализаций.
С другой стороны, есть несколько значений специального назначения или «виртуальных» коллекций, которые могут быть очень полезны как неизменяемые, такие как пустой набор и nCopies . Кроме того, существуют сторонние неизменяемые коллекции (например, Scala), которые могут вызывать существующий код Java, поэтому они оставляют возможность открывать неизменяемые коллекции наименее разрушительным образом.
источник