Koduję za pomocą wzorca stanu dla urządzenia osadzonego. Mam podstawową / abstrakcyjną klasę o nazwie State, a następnie każda dyskretna (konkretna) klasa stanu implementuje abstrakcyjną klasę State.
W klasie państwowej mam kilka metod abstrakcyjnych. Jeśli nie zaimplementuję metod abstrakcyjnych w klasie dyskretnej (konkretnej), Visual Studio wyświetli błąd podobny do tego:
... Błąd 1 „myConcreteState” nie implementuje dziedziczonego elementu abstrakcyjnego „myAbstractState”
Teraz: próbuję utworzyć właściwość String dla każdego stanu o nazwie StateName. Ilekroć tworzę nową konkretną klasę, muszę zdefiniować StateName. Chcę, aby VS zgłosił błąd, jeśli go nie użyję. Czy istnieje prosty sposób to zrobić?
Próbowałem tego w klasie abstrakcyjnej / podstawowej:
public abstract string StateName { get; set; }
Ale nie muszę wdrażać metod Get and Set w każdym stanie.
Zmienione pytanie: W idealnej sytuacji każda klasa stanu musiałaby mieć definicję StateName i być dziedziczona z abstrakcyjnej klasy podstawowej.
StateName = "MyState1"; //or whatever the state's name is
Jeśli brakuje tej instrukcji, Visual Studio wygeneruje błąd, jak opisano powyżej. Czy to możliwe, a jeśli tak, to w jaki sposób?
Odpowiedzi:
Myślę, że „poprawnym” sposobem na to jest posiadanie chronionego konstruktora w klasie bazowej, który wymaga nazwy stanu jako parametru.
Konkretne stany zapewniają publiczny konstruktor, który domyślnie wywołuje konstruktor klasy podstawowej o odpowiedniej nazwie.
Ponieważ klasa podstawowa nie ujawnia żadnych innych konstruktorów (ani chronionych, ani publicznych), każda dziedzicząca klasa musi przejść przez ten pojedynczy konstruktor, a zatem musi zdefiniować nazwę.
Pamiętaj, że nie musisz podawać nazwy podczas tworzenia konkretnego stanu, ponieważ zajmuje się tym jego konstruktor:
źródło
...:base(arg1, arg2)
! To było rozwiązanie, którego szukałem. To naprawdę pomaga utrzymać spójność kodowania mojego stanu.Od wersji C # 6 (uważam, że C #: nowa i ulepszona wersja C # 6.0 ) możesz tworzyć właściwości tylko dla gettera. Abyś mógł tak zadeklarować swoją klasę podstawową -
A następnie w swojej podklasie możesz
State
tak zaimplementować -A nawet dokładniej, używając operatora lambda -
Oba zawsze zwracałyby „stan_1” i były niezmienne.
źródło
public override string name { get; } = "State_1";
co nie wymaga za każdym razem ponownej oceny wartości.Twoje wymagania są sprzeczne:
vs.
Nie ma funkcji języka, która pozwala wymusić istnienie członka tylko w kilku podklasach. W końcu celem użycia superklasy jest poleganie na tym, że wszystkie podklasy będą miały wszystkich członków superklasy (i prawdopodobnie więcej). Jeśli chcesz stworzyć klasy, które działają jak
State
ale nie mają nazwy, to z definicji nie powinny (/ nie mogą) być podklasamiState
.Musisz albo zmienić swoje wymagania, albo użyć czegoś innego niż zwykłe dziedziczenie.
Możliwym rozwiązaniem z obecnym kodem może być uczynienie metody
State
nieabstrakcyjną i zwrócenie pustego ciągu.źródło
StateName = "MyState1"
w każdym stanie. Jeśli nie mam tej instrukcji w klasie stanu, idealnie Visual Studio wygeneruje błąd.return "MyState1"
jako swoją implementację i może dodać zmienną pamięć dla wartości, jeśli jest to potrzebne. Ale musisz wyjaśnić wymagania w pytaniu - czy każdy typ stanu wymaga StateName, którą można odczytać, i czy jakikolwiek stan wymaga mutacji po utworzeniu?