Estou codificando com um padrão de estado para um dispositivo incorporado. Eu tenho uma classe base / abstrata chamada State e, em seguida, cada classe de estado discreta (concreta) implementa a classe abstrata de estado.
Na classe estadual, tenho vários métodos abstratos. Se eu não implementar os métodos abstratos na classe discreta (concreta), o Visual Studio emitirá um erro semelhante a este:
... Erro 1 'myConcreteState' não implementa o membro abstrato herdado 'myAbstractState'
Agora: estou tentando criar uma propriedade String para cada estado chamado StateName. Sempre que crio uma nova classe concreta, preciso definir StateName. Quero que o VS gere um erro se não o usar. Existe uma maneira simples de fazer isso?
Eu tentei isso na classe abstract / base:
public abstract string StateName { get; set; }
Mas não preciso implementar os métodos Get e Set em cada estado.
Pergunta revisada: Em uma situação ideal, cada classe de estado teria que definir StateName e ser herdada da classe base abstrata.
StateName = "MyState1"; //or whatever the state's name is
Se essa instrução estiver faltando, o Visual Studio gerará um erro conforme descrito acima. Isso é possível e, se sim, como?
Respostas:
Eu acho que a maneira "correta" de fazer isso é ter um construtor protegido na classe base que requer o nome do estado como parâmetro.
Os estados concretos fornecem um construtor público que chama implicitamente o construtor da classe base com o nome apropriado.
Como a classe base não expõe outros construtores (nem protegidos nem públicos), cada classe herdada precisa passar por esse único construtor e, portanto, precisa definir um nome.
Observe que você não precisa fornecer o nome ao instanciar um estado concreto, porque o construtor cuida disso:
fonte
...:base(arg1, arg2)
! Esta é uma solução que eu estava procurando. Isso realmente ajuda a manter a codificação do meu estado mais consistente.A partir do C # 6 (acredito - C #: o C # 6.0 novo e aprimorado ), você é capaz de criar apenas propriedades getter. Então você pode declarar sua classe base assim -
E então, na sua subclasse, você pode implementar
State
assim -Ou até mais limpo usando o operador lambda -
Ambos sempre retornariam "State_1" e seriam imutáveis.
fonte
public override string name { get; } = "State_1";
e, portanto, não é necessário reavaliar o valor toda vez.Seus requisitos são uma contradição:
vs.
Não há nenhum recurso de idioma que permita forçar a existência de um membro em apenas algumas subclasses. Afinal, o objetivo de usar uma superclasse é confiar no fato de que todas as subclasses terão todos os membros da superclasse (e possivelmente mais). Se você deseja criar classes que agem como
State
mas não têm nome, então, por definição, elas (/ podem) não devem ser subclasses deState
.Você precisa alterar seus requisitos ou usar algo diferente da herança simples.
Uma possível solução com o código atual é tornar o método
State
não abstrato e retornar uma string vazia.fonte
StateName = "MyState1"
em cada Estado. Se eu não tiver essa instrução na classe state, o ideal é que o Visual Studio gere um erro.return "MyState1"
como implementação e pode adicionar armazenamento mutável para o valor, se necessário. Mas você precisa esclarecer os requisitos da pergunta - todo tipo de estado exige um StateName que possa ser lido e qualquer tipo de estado exige que ele seja modificado após a criação?