Объектно-ориентированное программирование

Дополнительные возможности ООП

Теоретические сведения

Цель работы

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

Задание

В этой работе:

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

Новые файлы

Использование классов из прошлых работ

Классы Point и Board напрямую берутся из 3 работы. Иерархия Input – из 4. Классы Game, AbstractState, StateBalda и StateXO будут переписаны для работы с исключениями и названы, соответственно, EGame, EAbstractState, EStateBalda и EStateXO.

Файл Exceptions.kt

Создайте класс:

open class GameException(message: String): Exception(message)

Создайте наследников этого класса:

  • объект WrongCommandException, который выбрасывается, если пользователь ввел неправильную команду;
  • объект object NoCellException, который выбрасывается, если пользователь ввел координаты поля, которого нет на игровой доске;
  • класс WrongStepException, объекты которого будут выбрасываться, если пользователь сделал ход не по правилам игры.
Новые классы

Класс StateList<T> содержит массив состояний и функции по работе с ним. Его конструктор выглядит следующим образом:

class StateList<T>(
    init: T,
    private val array: ArrayList<T> = ArrayList()
) 

В классе нужно реализовать две функции: fun add(state: T) – для добавления нового состояния после хода и fun move(to: Int): T для перехода к состоянию с индексом to. В случае, если состояние с индексом to отсутствует в массиве состояния, функция fun move(to: Int): T должна выбросить исключение WrongCommandException.

Также в класс нужно добавить свойство state – текущее состояние (как и раньше, оно не хранится отдельно, а выбирается геттером из массива состояний).

Класс-перечисление Turn имеет два объекта, один соответствует «крестику», другой – «нолику». Также в классе нужно определить функцию next(), которая возвращает противоположный для текущего объекта объект типа Turn, и функцию toString().

Новая реализация старых классов

Класс EAbstractState отличается от AbstractState функциями checkStep и step.

Функция open fun checkStep(step: Step): Unit теперь не возвращает результат, а в случае ошибки просто выбрасывает исключение.

Функции fun step(step: Step): EAbstractState теперь не контролирует ошибки, если происходит ошибка она пробрасывается мимо этой функции выше.

Свойство abstract val gameResult: String? по прежнему может возвращать нулевое значение, поскольку отсутствие результата игры это не ошибка.

Класс EStateXO отличается от StateXO только родительским классом.

Класс EStateBalda отличается от StateBalda родительским классом и функцией checkStep, в которой выбрасывается исключение в случае неверного числа параметров хода.

В классе EGame свойство states получает тип StateList. В функциях takeBack и step больше не нужны проверки и они не возвращают значение. Если при выполнении этих функций возникают ошибки, то они пробрасываются выше и будут обработаны в функции game.

Основное изменение в функции game заключается в том, что блок обработки ввода пользователя when помещается в блок try. В блоке catch перехватываются ошибки типа GameException и в выходной поток печатается сообщение из перехваченной ошибки.