Почему map не входит в collection

Обновлено: 07.07.2024

Вопросы и ответы по теме ООП (объектно ориентированное программирование) для собеседования по Java.

К списку вопросов по всем темам

Список всех вопросов по ООП

1. Назовите принципы ООП и расскажите о каждом.
2. Дайте определение понятию “класс”.
3. Что такое поле/атрибут класса?
4. Как правильно организовать доступ к полям класса?
5. Дайте определение понятию “конструктор”.
6. Чем отличаются конструкторы по умолчанию, копирования и конструктор с параметрами?
7. Какие модификации уровня доступа вы знаете, расскажите про каждый из них.
8. Расскажите об особенностях класса с единственным закрытым (private) конструктором.
9. О чем говорят ключевые слова “this”, “super”, где и как их можно использовать?
10. Дайте определение понятию “метод”.
11. Что такое сигнатура метода?
12. Какие методы называются перегруженными?
13. Могут ли нестатические методы перегрузить статические?
14. Расскажите про переопределение методов.
15. Может ли метод принимать разное количество параметров (аргументы переменной длины)?
16. Можно ли сузить уровень доступа/тип возвращаемого значения при переопределении метода?
17. Как получить доступ к переопределенным методам родительского класса?
18. Какие преобразования называются нисходящими и восходящими?
19. Чем отличается переопределение от перегрузки?
20. Где можно инициализировать статические/нестатические поля?

21. Зачем нужен оператор instanceof?
22. Зачем нужны и какие бывают блоки инициализации?
23. Каков порядок вызова конструкторов и блоков инициализации двух классов: потомка и его предка?
24. Где и для чего используется модификатор abstract?
25. Можно ли объявить метод абстрактным и статическим одновременно?
26. Что означает ключевое слово static?
27. К каким конструкциям Java применим модификатор static?
28. Что будет, если в static блоке кода возникнет исключительная ситуация?
29. Можно ли перегрузить static метод?
30. Что такое статический класс, какие особенности его использования?
31. Какие особенности инициализации final static переменных?
32. Как влияет модификатор static на класс/метод/поле?
33. О чем говорит ключевое слово final?
34. Дайте определение понятию “интерфейс”.
35. Какие модификаторы по умолчанию имеют поля и методы интерфейсов?
36. Почему нельзя объявить метод интерфейса с модификатором final или static?
37. Какие типы классов бывают в java (вложенные… и.т.д.)
38. Какие особенности создания вложенных классов: простых и статических.
39. Что вы знаете о вложенных классах, зачем они используются? Классификация, варианты использования, о нарушении инкапсуляции.
40. В чем разница вложенных и внутренних классов?
41. Какие классы называются анонимными?
42. Каким образом из вложенного класса получить доступ к полю внешнего класса?

43. Каким образом можно обратиться к локальной переменной метода из анонимного класса, объявленного в теле этого метода? Есть ли какие-нибудь ограничения для такой переменной?
44. Как связан любой пользовательский класс с классом Object?
45. Расскажите про каждый из методов класса Object.
46. Что такое метод equals(). Чем он отличается от операции ==.
47. Если вы хотите переопределить equals(), какие условия должны удовлетворяться для переопределенного метода?
48. Если equals() переопределен, есть ли какие-либо другие методы, которые следует переопределить?
49. В чем особенность работы методов hashCode и equals? Каким образом реализованы методы hashCode и equals в классе Object? Какие правила и соглашения существуют для реализации этих методов? Когда они применяются?
50. Какой метод возвращает строковое представление объекта?
51. Что будет, если переопределить equals не переопределяя hashCode? Какие могут возникнуть проблемы?
52. Есть ли какие-либо рекомендации о том, какие поля следует использовать при подсчете hashCode?
53. Как вы думаете, будут ли какие-то проблемы, если у объекта, который используется в качестве ключа в hashMap изменится поле, которое участвует в определении hashCode?
54. Чем отличается абстрактный класс от интерфейса, в каких случаях что вы будете использовать?
55. Можно ли получить доступ к private переменным класса и если да, то каким образом?
56. Что такое volatile и transient? Для чего и в каких случаях можно было бы использовать default?
57. Расширение модификаторов при наследовании, переопределение и сокрытие методов. Если у класса-родителя есть метод, объявленный как private, может ли наследник расширить его видимость? А если protected? А сузить видимость?
58. Имеет ли смысл объявлять метод private final?
59. Какие особенности инициализации final переменных?
60. Что будет, если единственный конструктор класса объявлен как final?
61. Что такое finalize? Зачем он нужен? Что Вы можете рассказать о сборщике мусора и алгоритмах его работы.
62. Почему метод clone объявлен как protected? Что необходимо для реализации клонирования?

Ответы. Часть 1

1. Назовите принципы ООП и расскажите о каждом.

Объе́ктно-ориенти́рованное программи́рование (ООП) — это методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования.

Основные принципы ООП: абстракция, инкапсуляция, наследование, полиморфизм.

Я был удивлен тем, что Map<. > не является Collection<?> .

Я думал, что это создаст много смысла, если бы оно было объявлено как таковое:

В конце концов, Map<K,V> представляет собой набор Map.Entry<K,V> , не так ли?

Так есть ли веская причина, почему это не реализовано как таковое?

Благодаря Cletus для наиболее авторитетного ответа, но мне все еще интересно, почему, если вы уже можете просматривать Map<K,V> как Set<Map.Entries<K,V>> (через entrySet() ), он не просто расширяет этот интерфейс.

Точно, interface Map<K,V> extends Set<Map.Entry<K,V>> было бы здорово!

но это обеспечивает очень ограниченную (и не особенно полезную) абстракцию Map .

Но если это так, то почему entrySet , заданный интерфейсом? Это должно быть полезно как-то (и я думаю, что легко спорить об этой позиции!).

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

Я не говорю, что все это к Map ! Он может и должен сохранять все другие методы (кроме entrySet , который теперь избыточен)!

Почему карта не расширяет коллекцию?

Обновление: Я думаю, что цитата отвечает на большинство вопросов. Стоит подчеркнуть, что часть коллекции не является особенно полезной абстракцией. Например:

(предполагая метод entry() , который создает экземпляр Map.Entry )

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

Возможно, вы могли бы сказать, что отношение equals() / hashCode() для Map.Entry было чисто ключевым, но даже с проблемами. Что еще более важно, действительно ли это добавляет какую-либо ценность? Вы можете обнаружить, что эта абстракция ломается, когда вы начинаете смотреть на угловые случаи.

Стоит отметить, что HashSet фактически реализован как HashMap , а не наоборот. Это чисто детализация реализации, но тем не менее интересно.

Основной причиной существования entrySet() является упрощение обхода, поэтому вам не нужно перемещаться по клавишам, а затем выполнять поиск ключа. Не считайте это prima facie доказательством того, что Map должен быть Set записей (imho).

Я думаю, почему это субъективно.

В Pharo Smalltak:

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

Что лучше субъективно.

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

Если вы посмотрите на соответствующую структуру данных, вы можете легко понять, почему Map не является частью Collection . В каждом Collection хранится одно значение, где в качестве Map хранится пара ключей и значений. Поэтому методы в интерфейсе Collection несовместимы для интерфейса Map . Например, в Collection имеем add(Object o) . Какова будет такая реализация в Map . Нет смысла иметь такой метод в Map . Вместо этого мы имеем метод put(key,value) в Map .

Тот же аргумент используется для методов addAll() , remove() и removeAll() . Поэтому основная причина заключается в том, что данные хранятся в Map и Collection .
Также, если вы помните интерфейс Collection реализованный интерфейс Iterable , то любой интерфейс с .iterator() должен возвращать итератор, который должен позволять нам перебирать значения, хранящиеся в Collection . Теперь, что бы такой метод возвращался для Map ? Ключевой итератор или Итератор значений? Это также не имеет смысла.

Есть способы, по которым мы можем перебирать ключи и значения, хранящиеся в Map , и именно так оно является частью структуры Collection .

Точно, interface Map<K,V> extends
Set<Map.Entry<K,V>> было бы здорово!

Причина, по которой я не хочу иметь interface Map<K,V> extends Set<Map.Entry<K,V>> , просто потому, что будет больше методов. И в конце концов, это разные вещи, верно? Также очень практически, если я ударил map. в среде IDE, я не хочу видеть .remove(Object obj) и .remove(Map.Entry<K,V> entry) , потому что я не могу сделать hit ctrl+space, r, return и делать с ним.

Карта имеет три разных набора: набор , набор записей и набор пар ключ-значение.
Вы можете получить любой из трех с помощью одного вызова метода.

Map<K,V> не следует расширять Set<Map.Entry<K,V>> , поскольку:

  • Вы не можете добавлять разные Map.Entry с тем же ключом к тому же Map , но
  • Вы можете добавить разные Map.Entry с тем же ключом к тому же Set<Map.Entry> .
К списку вопросов по всем темам

Вопросы

1. Дайте определение понятию “коллекция”.
2. Назовите преимущества использования коллекций.
3. Какие данные могут хранить коллекции?
4. Какова иерархия коллекций?
5. Что вы знаете о коллекциях типа List?
6. Что вы знаете о коллекциях типа Set?
7. Что вы знаете о коллекциях типа Queue?
8. Что вы знаете о коллекциях типа Map, в чем их принципиальное отличие?
9. Назовите основные реализации List, Set, Map.
10. Какие реализации SortedSet вы знаете и в чем их особенность?
11. В чем отличия/сходства List и Set?
12. Что разного/общего у классов ArrayList и LinkedList, когда лучше использовать ArrayList, а когда LinkedList?
13. В каких случаях разумно использовать массив, а не ArrayList?
14. Чем отличается ArrayList от Vector?
15. Что вы знаете о реализации классов HashSet и TreeSet?
16. Чем отличаются HashMap и TreeMap? Как они устроены и работают? Что со временем доступа к объектам, какие зависимости?
17. Что такое Hashtable, чем она отличается от HashMap? На сегодняшний день она deprecated, как все-таки использовать нужную функциональность?
18. Что будет, если в Map положить два значения с одинаковым ключом?
19. Как задается порядок следования объектов в коллекции, как отсортировать коллекцию?
20. Дайте определение понятию “итератор”.
21. Какую функциональность представляет класс Collections?
22. Как получить не модифицируемую коллекцию?
23. Какие коллекции синхронизированы?
24. Как получить синхронизированную коллекцию из не синхронизированной?
25. Как получить коллекцию только для чтения?
26. Почему Map не наследуется от Collection?
27. В чем разница между Iterator и Enumeration?
28. Как реализован цикл foreach?
29. Почему нет метода iterator.add() чтобы добавить элементы в коллекцию?
30. Почему в классе iterator нет метода для получения следующего элемента без передвижения курсора?
31. В чем разница между Iterator и ListIterator?
32. Какие есть способы перебора всех элементов List?
33. В чем разница между fail-safe и fail-fast свойствами?
34. Что делать, чтобы не возникло исключение ConcurrentModificationException?
35. Что такое стек и очередь, расскажите в чем их отличия?
36. В чем разница между интерфейсами Comparable и Comparator?
37. Почему коллекции не наследуют интерфейсы Cloneable и Serializable?

Ответы

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

1. Дайте определение понятию “коллекция”.

Коллекциями/контейнерами в Java принято называть классы, основная цель которых – хранить набор других элементов.

2. Назовите преимущества использования коллекций.

Массивы обладают значительными недостатками. Одним из них является конечный размер массива, как следствие, необходимость следить за размером массива. Другим — индексная адресация, что не всегда удобно, т.к. ограничивает возможности добавления и удаления объектов. Чтобы избавиться от этих недостатков уже несколько десятилетий программисты используют рекурсивные типы данных, такие как списки и деревья. Стандартный набор коллекций Java служит для избавления программиста от необходимости самостоятельно реализовывать эти типы данных и снабжает его дополнительными возможностями.

3. Какие данные могут хранить коллекции?

Коллекции могут хранить любые ссылочные типы данных.

4. Какова иерархия коллекций?

Иерархия коллекций Java

Здесь следует обратить внимание, что interface Map не входит в иерархию interface Collection.

С Java 1.6 классы TreeSet и TreeMap имплементируют интерфейсы NavigableSet и NavigableMap, которые расширяют интерфейсы SortedSet и SortedMap соответственно (SortedSet и SortedMap расширяют Set и Map).

5. Что вы знаете о коллекциях типа List?
6. Что вы знаете о коллекциях типа Set?
7. Что вы знаете о коллекциях типа Queue?

Методы remove() и poll() удаляют верхушку очереди и возвращают ее. Какой элемент будет удален (первый или последний) зависит от реализации очереди. Методы remove() и poll() отличаются лишь поведением, когда очередь пустая: метод remove() генерирует исключение, а метод poll() возвращает null .

Методы element() и peek() возвращают (но не удаляют) верхушку очереди.

java.util.Queue<E> реализует FIFO–буфер. Позволяет добавлять и получать объекты. При этом объекты могут быть получены в том порядке, в котором они были добавлены.

Реализации: java.util.ArrayDeque<E> , java.util.LinkedList<E> .

java.util.Deque<E> наследует java.util.Queue<E> . Двунаправленная очередь. Позволяет добавлять и удалять объекты с двух концов. Так же может быть использован в качестве стека.

Реализации: java.util.ArrayDeque<E> , java.util.LinkedList<E> .

8. Что вы знаете о коллекциях типа Map, в чем их принципиальное отличие?

Интерфейс java.util.Map<K,V> используется для отображения каждого элемента из одного множества объектов (ключей) на другое (значений). При этом, каждому элементу из множества ключей ставится в соответствие множество значений. В то же время одному элементу из множества значений может соответствовать 1, 2 и более элементов из множества ключей. Интерфейс java.util.Map<K,V> описывает функциональность ассоциативных массивов.

Реализации: java.util.HashMap<K,V> , java.util.LinkedHashMap<K,V> , java.util.TreeMap<K,V> , java.util.WeakHashMap<K,V> .

java.util.SortedMap<K,V> наследует java.util.Map<K,V> . Реализации этого интерфейса обеспечивают хранение элементов множества ключей в порядке возрастания (см. java.util.SortedSet). Реализации: java.util.TreeMap<K,V> .

9. Назовите основные реализации List, Set, Map.
Интерфейс Класс/Реализация Описание
List ArrayList Список
LinkedList Список
Vector Вектор
Stack Стек
Set HashSet Множество
TreeSet Множество
SortedSet (расширяющий интерфейс) Отсортированное множество
Map HashMap Карта/Словарь
TreeMap Карта/Словарь
SortedMap (расширяющий интерфейс) Отсортированный словарь
Hashtable Хеш-таблица
10. Какие реализации SortedSet вы знаете и в чем их особенность?
11. В чем отличия/сходства List и Set?

Оба унаследованы от Collection , а значит имеют одинаковый набор и сигнатуры методов. List хранит объекты в порядке вставки, элемент можно получить по индексу. Set не может хранить одинаковых элементов.

12. Что разного/общего у классов ArrayList и LinkedList, когда лучше использовать ArrayList, а когда LinkedList?

ArrayList реализован внутри в виде обычного массива . Поэтому при вставке элемента в середину, приходится сначала сдвигать на один все элементы после него, а уже затем в освободившееся место вставлять новый элемент. Зато в нем быстро реализованы взятие и изменение элемента – операции get, set , так как в них мы просто обращаемся к соответствующему элементу массива.

LinkedList реализован внутри по-другому. Он реализован в виде связного списка : набора отдельных элементов, каждый из которых хранит ссылку на следующий и предыдущий элементы. Чтобы вставить элемент в середину такого списка, достаточно поменять ссылки его будущих соседей. А вот чтобы получить элемент с номером 130, нужно пройтись последовательно по всем объектам от 0 до 130. Другими словами операции set и get тут реализованы очень медленно . Посмотри на таблицу:

Описание Операция ArrayList LinkedList
Взятие элемента get Быстро Медленно
Присваивание элемента set Быстро Медленно
Добавление элемента add Быстро Быстро
Вставка элемента add(i, value) Медленно Быстро
Удаление элемента remove Медленно Быстро

Если необходимо вставлять (или удалять) в середину коллекции много элементов, то лучше использовать LinkedList. Во всех остальных случаях – ArrayList.

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

13. В каких случаях разумно использовать массив, а не ArrayList?
14. Чем отличается ArrayList от Vector?

Vector deprecated. У Vector некоторые методы синхронизированы и поэтому они медленные. В любом случае Vector не рекомендуется использовать вообще.

15. Что вы знаете о реализации классов HashSet и TreeSet?

HashSet гораздо быстрее чем TreeSet (константное время против логарифмического для большинства операций, таких как add , remove , contains ), но TreeSet гарантирует упорядоченность объектов. Оба не синхронизированы.

16. Чем отличаются HashMap и TreeMap? Как они устроены и работают? Что со временем доступа к объектам, какие зависимости?

В целом ответ про HashSet и TreeSet подходит и к этому вопросу.

HashMap работает строго быстрее TreeMap .

17. Что такое Hashtable, чем она отличается от HashMap? На сегодняшний день она deprecated, как все-таки использовать нужную функциональность?

Некоторые методы HashTable синхронизированы, поэтому она медленнее HashMap .

  • HashTable синхронизирована, а HashMap нет.
  • HashTable не позволяет иметь null ключи или значения. HashMap позволяет иметь один null ключ и сколько угодно null значений.
  • У HashMap есть подкласс LinkedHashMap , который добавляет возможности по итерации. Если вам нужна эта функциональность, то можно легко переключаться между классами.
18. Что будет, если в Map положить два значения с одинаковым ключом?

Последнее значение перезапишет предыдущее.

19. Как задается порядок следования объектов в коллекции, как отсортировать коллекцию?

Класс ТгееМар полностью реализует интерфейс SortedMap . Он реализован как бинарное дерево поиска, значит его элементы хранятся в упорядоченном виде. Это значительно ускоряет поиск нужного элемента. Порядок задается либо естественным следованием элементов, либо объектом, реализующим интерфейс сравнения Comparator .

В этом классе четыре конструктора:

ТгееМар() — создает пустой объект с естественным порядком элементов;
TreeМар(Comparator с) — создает пустой объект, в котором порядок задается объектом сравнения с;
ТгееМар(Map f) — создает объект, содержащий все элементы отображения f, с естественным порядком его элементов;
ТгееМар(SortedMap sf) — создает объект, содержащий все элементы отображения sf, в том же порядке.

Интерфейс Comparator описывает два метода сравнения:

int compare(Object obj1, object obj2) — возвращает отрицательное число, если obj1 в каком-то смысле меньше obj2 ; нуль, если они считаются равными; положительное число, если obj1 больше obj2 . Для читателей, знакомых с теорией множеств, скажем, что этот метод сравнения обладает свойствами тождества, антисимметричности и транзитивности;

boolean equals(Object obj) — сравнивает данный объект с объектом obj , возвращая true , если объекты совпадают в каком-либо смысле, заданном этим методом.

Для каждой коллекции можно реализовать эти два метода, задав конкретный способ сравнения элементов, и определить объект класса SortedMap вторым конструктором. Элементы коллекции будут автоматически отсортированы в заданном порядке.

Почему Java Map не расширяет коллекцию?

Я был удивлен тем, что Map<. > не является Collection<?> .

Я думал, что было бы много смысла, если бы это было объявлено так:

В конце концов, это Map<K,V> коллекция Map.Entry<K,V> , не так ли?

Так есть ли веская причина, почему это не реализовано как таковое?

Спасибо Cletus за самый авторитетный ответ, но мне все еще интересно, почему, если вы уже можете просматривать Map<K,V> как Set<Map.Entries<K,V>> (через entrySet() ), он не просто расширяет этот интерфейс.

Если a Map является a Collection , каковы элементы? Единственный разумный ответ - «Пары ключ-значение»

Точно, interface Map<K,V> extends Set<Map.Entry<K,V>> было бы здорово!

но это обеспечивает очень ограниченную (и не особо полезную) Map абстракцию.

Но если это так, то почему entrySet указывается интерфейс? Это должно быть как-то полезно (и я думаю, что легко отстаивать эту позицию!).

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

Я не говорю, что это все, что нужно сделать Map ! Он может и должен сохранять все другие методы (кроме entrySet , который сейчас избыточен)!

Почему карта не расширяет коллекцию?

Это было разработано. Мы считаем, что отображения не являются коллекциями, а коллекции не являются отображениями. Таким образом, для Map не имеет смысла расширять интерфейс Collection (или наоборот).

Если карта является коллекцией, каковы элементы? Единственный разумный ответ - «Пары ключ-значение», но это обеспечивает очень ограниченную (и не особо полезную) абстракцию карты. Вы не можете спросить, к какому значению относится данный ключ, и не можете удалить запись для данного ключа, не зная, к какому значению он соответствует.

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

Карты можно просматривать как Коллекции (ключей, значений или пар), и этот факт отражен в трех «Операциях просмотра коллекций» на Картах (keySet, entrySet и values). Хотя в принципе можно просматривать список как индексы сопоставления карты с элементами, у него есть неприятное свойство, заключающееся в том, что удаление элемента из списка изменяет ключ, связанный с каждым элементом перед удаленным элементом. Вот почему у нас нет операции просмотра карты в списках.

Обновление: я думаю, что цитата отвечает на большинство вопросов. Стоит подчеркнуть, что коллекция записей не является особенно полезной абстракцией. Например:

(предполагая entry() метод, который создает Map.Entry экземпляр)

Map Требуются уникальные ключи, так что это нарушит это. Или, если вы наложите уникальные ключи на Set записи, это не совсем Set в общем смысле. Это Set с дополнительными ограничениями.

Можно сказать, что отношение equals() / было чисто ключевым, но даже в этом есть проблемы. Что еще более важно, действительно ли это добавляет ценность? Вы можете обнаружить, что эта абстракция рушится, когда вы начинаете смотреть на угловые случаи. hashCode() Map.Entry

Стоит отметить, что на HashSet самом деле реализован как, а HashMap не наоборот. Это чисто деталь реализации, но, тем не менее, интересно.

Основная причина entrySet() существования - это упрощение обхода, чтобы вам не приходилось обходить ключи, а затем выполнять поиск ключа. Не принимайте это как доказательство prima facie, что a Map должно быть Set из записей (imho).

Обновление очень убедительно, но, действительно, представление Set, возвращаемое функцией entrySet() действительно, поддерживает remove , хотя и не поддерживает add (вероятно, выдает UnsupportedException ). Итак, я понимаю вашу точку зрения, но опять же, я также вижу точку зрения ОП .. (Мое собственное мнение соответствует изложенному в моем собственном ответе ..) Цвей поднимает хороший вопрос. Все эти сложности add могут быть обработаны так же, как это entrySet() делает вид: разрешить одни операции и не разрешить другие. Естественным ответом, конечно же, является «Какого рода Set не поддерживает add ?» - хорошо, если такое поведение приемлемо entrySet() , то почему оно не приемлемо для this ? То есть , я имею в основном убежден уже о том, почему это не такая большая идея , как я когда - то мысли, но я до сих пор считаю , что это достойно дальнейшего обсуждения, если только обогатить свое собственное понимание того , что делает дизайн хороший API / ООП. Первый абзац цитаты из FAQ смешной: «Мы чувствуем . таким образом . мало смысла». Я не чувствую, что «чувство» и «чувство» формируют заключение; о) Коллекция может быть сделана для расширения карты ? Не уверен, почему автор думает о Collection расширении Map ?

Проблема здесь в том, что наследование моделирует только один тип общности. Если вы выберете две вещи, которые кажутся «похожими на коллекцию», вы можете выбрать 8 или 10 общих для них вещей. Если вы выберете другую пару «коллекционных» вещей, у них также будет 8 или 10 общих черт, но они не будут такими же, как в первой паре.

Если вы посмотрите на дюжины различных «коллекции, как» вещи, практически каждый из них, вероятно , что - то вроде 8 или 10 общих характеристик, по меньшей мере , один другой , - но если вы посмотрите на то , что общими для каждого одного из них у вас осталось практически ничего.

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

Некоторые также используют вариант, в основном говоря: «этот тип коллекции поддерживает операцию X, но вы не можете использовать ее, наследуя от базового класса, который определяет X, но пытаясь использовать производный класс« X, не удается (например, , бросив исключение).

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

Читайте также: