#java #ооп
Написал односвязный список на Java. В нем сделал методы insertFirst(T item) insertLast(T item) insert(int position, T item) removeFirst() removeLast() remove(int position) get(int position) isEmpty() В моей реализации односвязного списка есть указатель на первый элемент списка. Этот класс называется LinkedListWithHead. Далее, я хочу написать еще одну реализацию односвязного списка, но используя уже указатель на первый и на последний элемент списка. Этот класс будет называться LinkedListWithHeadAndTail. Изменится реализация методов insertFirst insertLast removeFirst removeLast` То есть, по сути, большую часть методов я вообще трогать не буду, поэтому не хочется заводить совсем новый класс и там все эти методы дублировать. Но и наследование как то не очень тут вяжется, потому что LinkedListWithHeadAndTail не является разновидностью LinkedListWithHead. И вообще, пользователям моих классов может быть важно написать метод, принимающей исключительно объекты класса LinkedListWithHead, потому что они экономичнее по памяти. А если я завяжусь на наследовании, то в такой метод можно будет передать и объект класса LinkedListWithHeadAndTail. Может быть композиция будет выходом для меня? Если вложить объект класса LinkedlistWithHead в LinkedListWithHeadAndTail
Ответы
Ответ 1
Наследование нужно использовать если между новым и старым типами есть отношение Is-A: новый тип есть разновидность старого, и везде, где использовался объект старого типа, можно использовать и объект нового. Использование наследования лишь для того, чтобы скопировать большую часть реализации — злоупотребление наследованием. Так делают довольно часто (особенно если язык не предоставляет удобных возможностей повторного использования реализации без наследования), но это неправильно, и может потенциально привести к проблемам. Для вашего случая мне кажутся возможными два пути. Вы заводите внутренний класс со статическими функциями-утилитами, и используете его в обеих реализациях. В этот новый класс (который по сути лишь контейнер методов) можно выгрузить общий код. Вы заводите абстрактный суперкласс и помещаете общую функциональность туда. Это решение наверное удобнее в имплементации, но оно всё же определённо хуже, т. к. в наследовании участвует этот самый суперкласс, у которого вовсе нет отдельного смысла, он лишь деталь имплементации.Ответ 2
Я думаю стоит посмотреть как реализовано в Java Collection Framework. Т.к. по-сути он очень хорошо спроектирован и является отличным примером. Если открыть исходники, то можно увидеть, что для списков используется абстрактный параметризированный класс AbstractListкоторый реализует интерфейс List и является дочерним по отношению к AbstractCollection Т.е. в интерфейсе необходимо объявить ряд общих методов для списков, в абстрактном классе реализовать общую логику ну и в дочерних классах LinkedListWithHead и LinkedListWithHeadAndTail уже детали реализации.
Комментариев нет:
Отправить комментарий