Возврат экземпляра базового класса из вызовов производного класса - PullRequest
0 голосов
/ 13 октября 2019

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

Базовый класс является общим, так что вы можете указать, чем должна заполняться каждая ячейка.

public class Board<T> { /* various usefule routines that return new instances of Board<T> */ }

Я начинаю с игры TicTacToe, объявленной так:

public enum TicTacMove { Empty, X, O };

public class TicTacToe : Board<TicTacMove> { /* ... */ }

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

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

Ошибка CS0266 Не удается неявно преобразовать тип 'BoardGames.Board 'to' BoardGames.TicTacToe.TicTacToe '. Существует явное преобразование (вы пропустили приведение?)

Итак, я явным образом приведу его, что затем дает мне InvalidCastException:

Невозможно привести объект типаBoardGames.Board`1 [BoardGames.TicTacToe.TicTacMove] ', чтобы набрать' BoardGames.TicTacToe.TicTacToe '

Если бы мой класс содержал изменяемые данные, я мог бы просто изменить данные на месте и не беспокоиться оЭто;Мой вопрос заключается в том, как добиться этого, возвращая новый экземпляр, чтобы каждый экземпляр был неизменным.

Редактировать: Например, базовый класс имеет этот конструктор:

 public Board(Board<T> Source, IEnumerable<(int Index, T Value)> Changes)

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

1 Ответ

0 голосов
/ 14 октября 2019

Хорошо, я понял это.

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

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

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

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

В качестве примера (грубый псевдокод вперед)

public abstract class BaseClass {
  protected BaseClass(BaseClass Source, var changes...) ...
}

public class DerivedClass {
  private DerivedClass(DerivedClass Source, var changes)
    : BaseClass(Source, changes) { }

public DerivedClass MakeChange(var change) {
  ...set up changed values...
  return new DerivedClass(this, changes)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...