Ta strategia polega na zastąpieniu takich:
public class Politician
{
public const int Infidelity = 0;
public const int Embezzlement = 1;
public const int FlipFlopping = 2;
public const int Murder = 3;
public const int BabyKissing = 4;
public int MostNotableGrievance { get; set; }
}
Z:
public class Politician
{
public MostNotableGrievance MostNotableGrievance { get; set; }
}
public class MostNotableGrievance
{
public static readonly MostNotableGrievance Infidelity = new MostNotableGrievance(0);
public static readonly MostNotableGrievance Embezzlement = new MostNotableGrievance(1);
public static readonly MostNotableGrievance FlipFlopping = new MostNotableGrievance(2);
public static readonly MostNotableGrievance Murder = new MostNotableGrievance(3);
public static readonly MostNotableGrievance BabyKissing = new MostNotableGrievance(4);
public int Code { get; private set; }
private MostNotableGrievance(int code)
{
Code = code;
}
}
Dlaczego właśnie tak jest preferowane, aby typ był wyliczeniem, tak jak poniżej:
public class Politician
{
public MostNotableGrievance MostNotableGrievance { get; set; }
}
public enum MostNotableGrievance
{
Infidelity = 0,
Embezzlement = 1,
FlipFlopping = 2,
Murder = 3,
BabyKissing = 4
}
Z typem nie wiąże się żadne zachowanie, a jeśli tak, to i tak używałbyś innego rodzaju refaktoryzacji, na przykład „Zamień kod typu na podklasy” + „Zamień warunkowo na polimorfizm”.
Jednak autor wyjaśnia, dlaczego marszczy brwi wobec tej metody (w Javie?):
Kody typów numerycznych lub wyliczenia są wspólną cechą języków opartych na języku C. Dzięki symbolicznym nazwom mogą być dość czytelne. Problem polega na tym, że nazwa symboliczna jest tylko pseudonimem; kompilator nadal widzi liczbę bazową. Typ kompilatora sprawdza, używając liczby 177, a nie nazwy symbolicznej. Każda metoda, która przyjmuje kod typu jako argument, oczekuje liczby i nic nie zmusza do użycia nazwy symbolicznej. Może to zmniejszyć czytelność i być źródłem błędów.
Ale podczas próby zastosowania tej instrukcji do C #, ta instrukcja wydaje się nieprawdziwa: nie przyjmie liczby, ponieważ wyliczenie jest faktycznie uważane za klasę. Więc następujący kod:
public class Test
{
public void Do()
{
var temp = new Politician { MostNotableGrievance = 1 };
}
}
Nie będzie się kompilować. Czy zatem refaktoryzację można uznać za niepotrzebną w nowszych językach wysokiego poziomu, takich jak C #, czy też nie rozważam czegoś?
źródło
var temp = new Politician { MostNotableGrievance = MostNotableGrievance.Embezzlement };
Odpowiedzi:
Myślę, że prawie odpowiedziałeś na własne pytanie.
Drugi fragment kodu jest lepszy niż pierwszy, ponieważ zapewnia bezpieczeństwo typu. W pierwszej części, jeśli masz podobne wyliczenie Ryb, możesz powiedzieć coś takiego
i kompilator nie będzie się tym przejmował. Jeśli Fish.Haddock = 2, powyższe będzie dokładnie równoważne z
ale oczywiście nie od razu czytelne jako takie.
Powodem, dla którego wyliczenia często nie są lepsze, jest to, że niejawna konwersja do i z int pozostawia ci dokładnie ten sam problem.
Ale w języku C # nie ma takiej niejawnej konwersji, więc wyliczenie jest lepszą strukturą do użycia. Rzadko zobaczysz jedno z dwóch pierwszych zastosowanych podejść.
źródło
Jeśli nie ma żadnego zachowania związanego z wartością i nie ma żadnych dodatkowych informacji, które należy przechowywać obok niej, a język nie obsługuje niejawnej konwersji na liczby całkowite, użyłbym wyliczenia; po to są.
źródło
Kolejny przykład, który może ci pomóc, znajdziesz w Effective Java (pozycja 30, jeśli chcesz to sprawdzić). Dotyczy to również C #.
Załóżmy, że używasz stałych int do modelowania różnych zwierząt, na przykład węży i psów.
Załóżmy, że są to stałe, a może nawet zdefiniowane w różnych klasach. Może ci się to wydawać w porządku i może się naprawdę udać. Ale rozważ ten wiersz kodu:
Oczywiście jest to błąd. Kompilator nie będzie narzekał i kod zostanie wykonany. Ale twój wąż nie zmieni się w psa. Jest tak, ponieważ kompilator widzi tylko:
Twój wąż jest właściwie pytonem (a nie terierem). Ta funkcja nazywa się bezpieczeństwem typu i jest właściwie powodem, dla którego jesteś przykładowym kodem
nie skompiluje się. MostNotableGrievance to MostNotableGrievance, a nie liczba całkowita. Za pomocą wyliczeń możesz wyrazić to w systemie pisma. I dlatego myślę, że Martin Fowler i wyliczenia są świetne.
źródło