Дополнительные возможности ООП
Теоретические сведения
Цель работы
Научится использовать обработку ошибок, параметризацию классов и другие возможности ООП для улучшения структуры программы.
Задание
В этой работе:
- с помощью механизма исключений будет добавлен вывод информации об ошибках, допущенных пользователем при вводе хода или команды;
- с помощью параметризованного класса из класса 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
и в выходной поток печатается сообщение из перехваченной ошибки.