Wydaje mi się, że klasa boolowska jest idealnym kandydatem do wdrożenia jako wyliczenie.
Patrząc na kod źródłowy, większość klas to metody statyczne, które można przenieść bez zmian do wyliczenia, reszta staje się znacznie prostsza jako wyliczenie. Porównaj oryginał (usunięte komentarze i metody statyczne):
public final class Boolean implements java.io.Serializable,
Comparable<Boolean>
{
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
private final boolean value;
public Boolean(boolean value) {
this.value = value;
}
public Boolean(String s) {
this(toBoolean(s));
}
public boolean booleanValue() {
return value;
}
public String toString() {
return value ? "true" : "false";
}
public int hashCode() {
return value ? 1231 : 1237;
}
public boolean equals(Object obj) {
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
public int compareTo(Boolean b) {
return compare(this.value, b.value);
}
}
z wersją enum:
public enum Boolean implements Comparable<Boolean>
{
FALSE(false), TRUE(true);
private Boolean(boolean value) {
this.value = value;
}
private final boolean value;
public boolean booleanValue() {
return value;
}
public String toString() {
return value ? "true" : "false";
}
}
Czy jest jakiś powód, dla którego Boolean nie mógł zostać enum?
Jeśli jest to kod Sun zastępujący metodę equals (), brakuje bardzo podstawowej kontroli porównania referencji dwóch obiektów przed porównaniem ich wartości. Tak myślę, że metoda equals () powinna być:
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
java
api
source-code
Highland Mark
źródło
źródło
if
), ale z punktu widzenia teorii konceptualnej / typów logiczne i wyliczenia są zarówno typami sum, więc myślę, że sprawiedliwe jest pytanie, dlaczego nie wypełnić lukę między nimi.valueOf(String)
(która kolidowałaby z wartością enum wyliczenia) i magię,getBoolean
która może sprawić, że będzie onaBoolean.valueOf("yes")
zwracać prawdę, a nie fałsz. Oba są częścią specyfikacji 1.0 i wymagałyby odpowiedniej kompatybilności wstecznej.Odpowiedzi:
Cóż, myślę, że mógłbym zacząć od argumentowania, że wyliczenia Java nie zostały dodane do języka programowania Java do JDK 1.5. i dlatego to rozwiązanie nie było nawet alternatywą we wczesnych dniach, kiedy zdefiniowano klasę logiczną.
Biorąc to pod uwagę, Java ma reputację polegającą na zachowaniu wstecznej kompatybilności między wydaniami, więc nawet jeśli dzisiaj możemy uznać twoje rozwiązanie za dobrą alternatywę, nie możemy tego zrobić bez zerwania tysięcy linii kodu już przy użyciu starej logiki Boolean klasa.
źródło
new Boolean("True")
Inew Boolean("true")
może również powodować pewne problemy z hipotetycznym realizacji enum.Niektóre rzeczy nie działają i nie działają w dość zaskakujący sposób, gdy porównasz je z poprzednią funkcjonalnością wartości logicznej Java.
Zignorujemy boks, ponieważ dodano coś do 1.5. Hipotetycznie, gdyby Sun tego chciał, mogliby sprawić,
enum Boolean
by zachowywał się tak, jak boks wykonywany naclass Boolean
.Istnieją jednak inne zaskakujące (dla kodera) sposoby, które nagle by się zepsuły w porównaniu z funkcjonalnością wcześniejszej klasy.
Problem valueOf (String)
Prostym przykładem tego jest:
Uruchomienie tego kodu daje:
Problem polega na tym, że nie mogę przejść przez cokolwiek, co nie jest
TRUE
lubFALSE
do czegovalueOf(String)
.W porządku ... zastąpimy to naszą własną metodą ...
Ale ... jest tu problem. Nie można przesłonić metody statycznej .
I tak cały kod, który jest przekazywany
true
lubTrue
inne pomieszane przypadki będą błędne - i całkiem spektakularnie z wyjątkiem środowiska wykonawczego.Więcej zabawy z valueOf
Istnieje kilka innych bitów, które nie działają zbyt dobrze:
Po
foo
prostu dostaję ostrzeżenie o boksowaniu już zapakowanej wartości. Jednak kod paska jest błędem składni:Jeśli zmuszymy ten błąd składniowy z powrotem do
String
typu:Odzyskujemy nasz błąd czasu wykonania:
Dlaczego ktoś miałby to napisać? Nie wiem ... ale kod, który kiedyś działał i już nie działał.
Nie zrozumcie mnie źle, naprawdę podoba mi się pomysł, aby kiedykolwiek mieć tylko jedną kopię danego niezmiennego obiektu. Wyliczenie rozwiązuje ten problem. Osobiście spotkałem się z kodem dostawcy, który zawierał błędy w kodzie dostawcy, który wyglądał mniej więcej tak:
to nigdy nie zadziałało (nie, nie naprawiłem tego, ponieważ nieprawidłowy stan został naprawiony gdzie indziej, a naprawienie tego zepsuło to w dziwny sposób, że tak naprawdę nie miałem czasu na debugowanie) . Gdyby to był wyliczenie, kod działałby zamiast tego.
Jednak konieczność składni wokół wyliczenia (rozróżniana jest wielkość liter - zagłęb się w enumConstantDirectory z tyłu
valueOf
, błędy w czasie wykonywania, które muszą działać w ten sposób dla innych wyliczeń) i sposób działania metod statycznych powoduje uszkodzenie szeregu rzeczy, które uniemożliwiają będący kroplą zastępującą wartość logiczną.źródło
of
lubfrom
odpowiednią metodę javadoc.valueOf
i Boolean.valueOf () istnieje tam od 1.0 . Albo Enums nie byłby w stanie użyć valueOf jako metody statycznej, albo Boolean potrzebowałby innej metody niż ta, której używał. Robienie albo łamie konwencję, albo zgodność - i nie posiadanie logicznego enum nie powoduje złamania. Z tego wybór jest dość prosty.Boolean.valueOf(Boolean.valueOf("TRUE"))
istnieją dwa różnevalueOf
sposoby:valueOf(String)
avalueOf(boolean)
. Błąd składni, ponieważ zapomniał wdrożyćvalueOf(boolean)
inMyBoolean
. Następnie następuje automatyczne skasowanie między dwoma wywołaniami, które jest zakodowane na stałe w języku,Boolean
ale nie.MyBoolean
Jeśli zaimplementowałeśvalueOf(boolean)
MyBoolean.valueOf(MyBoolean.valueOf("FALSE").booleanValue())
działaNajprawdopodobniej dlatego, że
boolean
typ pierwotny nie jestEnum
, a wersje pudełkowe typów pierwotnych zachowują się prawie identycznie jak ich wersja nieopakowana. Na przykład(Wydajność może nie być taka sama, ale to inny temat.)
Byłoby dziwnie, gdybyś mógł napisać:
ale nie:
źródło
if
działał tak, jak obecnie. Z drugiej strony nie można zignorować faktu, że dodałeś doBoolean
tego dodatkową funkcjonalność ,boolean
której nie ma.Oprócz
valueOf
problemu (który jest problemem na poziomie Java, może działać dobrze na poziomie JVM), ponieważBoolean
ma publiczny konstruktor. To był zły pomysł, obecnie nieaktualny, ale na pewno zostanie.źródło
Powodem jest to, że „bool” był częścią języka Java znacznie wcześniej niż „enum”. Przez wiele lat „bool” był bardzo pożądany, a „enum” nie było dostępne. Dopiero teraz możesz powiedzieć „gdyby od początku dostępny był wylicznik, to moglibyśmy zaimplementować bool jako wyliczenie zamiast osobnego typu”.
W Swift, który mógł wyrazić „bool” jako wyliczenie, istnieją trzy struktury o nazwach „Bool”, „DarwinBoolean” i „ObjCBool” implementujące protokół „ExpressibleByBooleanLiteral”. (DarwinBoolean jest kompatybilny z boolem C lub C ++, ObjCBool jest kompatybilny z BOOLem Objective-C). „true” i „false” są specjalnymi wartościami rozpoznawanymi przez kompilator i można ich używać tylko do inicjowania obiektów obsługujących protokół „ExpressibleByBooleanLiteral”. Bool ma wewnętrzną zmienną „_value” zawierającą jednobitową liczbę całkowitą.
Więc Bool nie jest częścią języka Swift, ale standardowej biblioteki. true i false są częścią języka, podobnie jak protokół ExpressibleByBooleanLiteral.
źródło