Я кодирую с шаблоном состояния для встроенного устройства. У меня есть базовый / абстрактный класс, называемый State, и затем каждый дискретный (конкретный) класс состояний реализует абстрактный State State.
В государственном классе у меня есть несколько абстрактных методов. Если я не реализую абстрактные методы в дискретном (конкретном) классе, Visual Studio выдаст ошибку примерно так:
... Ошибка 1 'myConcreteState' не реализует унаследованный абстрактный член 'myAbstractState'
Теперь: я пытаюсь создать свойство String для каждого состояния с именем StateName. Всякий раз, когда я создаю новый конкретный класс, мне нужно определить StateName. Я хочу, чтобы VS выдавал ошибку, если я ее не использую. Есть ли простой способ сделать это?
Я пробовал это в абстрактном / базовом классе:
public abstract string StateName { get; set; }
Но мне не нужно реализовывать методы Get и Set в каждом государстве.
Пересмотренный вопрос: в идеальной ситуации каждый класс состояний должен иметь определения StateName и наследоваться от абстрактного базового класса.
StateName = "MyState1"; //or whatever the state's name is
Если это утверждение отсутствует, Visual Studio выдаст ошибку, как описано выше. Возможно ли это, и если да, то как?
Ответы:
Я предполагаю, что «правильный» способ сделать это - иметь защищенный конструктор в базовом классе, который требует имя состояния в качестве параметра.
Затем конкретные состояния предоставляют открытый конструктор, который неявно вызывает конструктор базового класса с соответствующим именем.
Поскольку базовый класс не предоставляет никаких других конструкторов (ни защищенных, ни общедоступных), каждый наследующий класс должен пройти через этот единственный конструктор и, следовательно, должен определить имя.
Обратите внимание, что вам не нужно указывать имя при создании конкретного состояния, потому что его конструктор позаботится об этом:
источник
...:base(arg1, arg2)
! Это решение, которое я искал. Это действительно помогает сделать кодирование моего состояния более последовательным.Начиная с C # 6 (я верю - C #: новый и улучшенный C # 6.0 ), вы можете создавать свойства только для геттеров. Таким образом, вы можете объявить свой базовый класс следующим образом:
И тогда в вашем подклассе вы можете реализовать
State
так -Или даже аккуратнее, используя лямбда-оператор -
Оба всегда возвращали бы «State_1» и были бы неизменными.
источник
public override string name { get; } = "State_1";
что тогда не нужно переоценивать значение каждый раз.Ваши требования противоречат:
против
Там нет языковой функции, которая позволяет вам форсировать существование члена только в нескольких подклассах. В конце концов, смысл использования суперкласса заключается в том, чтобы полагаться на тот факт, что у всех подклассов будут все члены суперкласса (и, возможно, больше). Если вы хотите создать классы, которые действуют как,
State
но не имеют имени, то по определению они не должны (/ могут) быть подклассамиState
.Вы должны либо изменить свои требования, либо использовать что-то кроме простого наследования.
Возможное решение с использованием кода в том виде, в каком оно есть, - сделать метод
State
не абстрактным и вернуть пустую строку.источник
StateName = "MyState1"
в каждом государстве. Если у меня нет этого оператора в классе состояний, то в идеале Visual Studio выдаст ошибку.return "MyState1"
качестве своей реализации и может добавить изменяемое хранилище для значения, если оно им нужно. Но вам нужно уточнить требования в вопросе - требует ли каждый тип состояния StateName, которое может быть прочитано, и требует ли какой-либо тип состояния его мутирование после создания?