Wenn ich den Java -Code in den Ceylon -Code umwandelst, begegne ich manchmal einige Java -Klassenkonstruktoren, die die Überprüfung und Initialisierung verwirren. Verwenden wir ein einfaches, aber künstliches Codebeispiel, um zu veranschaulichen, was ich erklären möchte.
Ein schlechter Code
Betrachten Sie die folgende Java -Klasse. (Mann, schreibe solchen Code nicht zu Hause)
öffentliche Klassenperiode {privates Enddatum startdate; privates Enddatum Enddate; // kehrt null zurück, wenn die angegebene Zeichenfolge // kein gültiges Datum private Datum an ParseDate (String -Datum) {...} öffentliche Periode (String Start, String End) {startDate = ParseDate (start) darstellt; Enddate = ParseDate (Ende); } public boolean isvalid () {return startDate! = null && enddate! = null; } public date getStartDate () {if (startDate == null) werfen neue illegaleStateException (); Startdate zurückgeben; } public date getendDate () {if (enddate == null) werfen neue illegaleStateException (); Enddate zurückgeben; }}Hey, ich habe es schon einmal gewarnt, es ist künstlich. Es ist jedoch eigentlich nicht ungewöhnlich, so etwas im tatsächlichen Java -Code zu finden.
Das Problem hierfür ist, dass wir auch dann, wenn die Überprüfung der Eingabeparameter (in der versteckten ParseDate () -Methode) fehlschlägt, immer noch eine Instanz von Zeitraum erhalten. Aber die Zeit, die wir erhalten, ist kein "gültiger" Zustand. Was meine ich streng genommen, was meine ich?
Wenn ein Objekt nicht sinnvoll auf eine öffentliche Operation reagieren kann, würde ich sagen, dass es sich in einem nicht-validischen Zustand befindet. In diesem Beispiel werfen GetStartDate () und getenddate () eine illegale StateException -Ausnahme aus, was ein Fall ist, von dem ich nicht "sinnvoll" halte.
Wenn wir uns dieses Beispiel hingegen betrachten, sind wir beim Entwurfsperiode hier in der Art Sicherheit nicht gescheitert. Unkontrollierte Ausnahmen stellen eine "Lücke" im Typsystem dar. Daher wäre ein besseres Entwurf des Typs von Typ-Safe eine nicht benutzte nicht kontrollierte Ausnahmen-In diesem Beispiel wird IllegalStateException nicht geworfen.
(In der Tat, in realer Code, begegnen ich eher auf eine GetStartDate () -Methode, die nach dieser Codezeile nicht auf NULL prüft, was zu einer NullPointerexception -Ausnahme führt, was noch schlimmer ist.)
Wir können die obige Periodenklasse leicht in eine Klasse von Ceylon -Form umwandeln:
Shared Class Periode (String Start, String End) {// gibt NULL zurück, wenn die angegebene Zeichenfolge // kein gültiges Datum darstellt? ParseDate (String -Datum) => ...; Wert mayBestartDate = ParseDate (Start); Wert martendDate = ParseDate (Ende); Shared boolean valid => MayBestartDate existiert &&anterDate existiert; Shared Datum StartDate {Assert (existiert MayBestartDate); kehren Sie MayBestartDate zurück; } Shared Datum Enddate {Assert (existiert MayBestartDate); kehren Sie MayBestartDate zurück; } Shared Datum Enddate {assert (existiert vielleicht weiterdDate); Rückkehr vielleicht }}Natürlich wird dieser Code auch auf dieselben Probleme wie den ursprünglichen Java -Code stoßen. Zwei ordnungsgemäße Symbole rief uns an, es gab ein Problem in der Art Sicherheit des Codes.
Machen Sie den Java -Code besser
Wie verbessern wir diesen Code in Java? Nun, hier ist ein Beispiel für Javas kritisierte überprüfte Ausnahmen, die sehr vernünftig zu lösen sind! Wir können den Zeitraum leicht ändern, um eine geprüfte Ausnahme aus seinem Konstruktor auszulegen:
öffentliche Klassenperiode {privates Enddatum startdate; privates Enddatum Enddate; // löscht, wenn die angegebene Zeichenfolge // kein gültiges Datum privates Datum an ParseDate (String Datum) darstellt, löscht DateFormatexception {...} öffentliche Periode (String Start, String End) aus DateFormatexception {startDate = ParseDate (start); Enddate = ParseDate (Ende); } public date getStartDate () {return startDate; } public date getendDate () {return EndDate; }}Mit dieser Lösung werden wir jetzt keinen Zeitraum in einem nicht-validischen Zustand bekommen. Der Code, der den Zeitraum instanziiert, wird vom Compiler behandelt, um ungültige Eingänge zu verarbeiten, wodurch eine Ausnahme von DateFormatexception erfasst wird.
Versuchen Sie {Periode p = neue Periode (Start, Ende); ...} catch (DateFormatexception dfe) {...}Dies ist eine nette, perfekte und korrekte Verwendung von überprüften Ausnahmen, und leider sehe ich Java -Code selten mit überprüften Ausnahmen wie dem oben genannten.
Machen Sie den Ceylon -Code besser
Wie wäre es mit Ceylon? Ceylon hat keine geprüften Ausnahmen, daher müssen wir eine andere Lösung finden. Normalerweise ruft Ceylon in einer Situation, in der Java eine Funktion aufruft und eine geprüfte Ausnahme ausführt, die Funktion auf und gibt einen Gewerkschaftstyp zurück. Da die Initialisierung einer Klasse nur die Klasse selbst zurückgibt, müssen wir eine gemischte Initialisierungs-/Überprüfungslogik extrahieren, um sie zu einer Fabrikfunktion zu machen.
// Rückgabe dateFormaterror Wenn die angegebene Zeichenfolge kein gültiges datiertes | DateFormaterRor -ParseDate (String -Datum) => ...; Shared Periode | DateFormaterror Parseperiod (String Start, String End) {Value StartDate = ParseDate (Start); if (ist dateFormaterror startDate) {return startDate; } value EndDate = ParseDate (Ende); if (is dateFormaterror enddate) {return Enddate; } Rückgabeperiode (StartDate, Enddate);} Shared Class Periode (StartDate, Enddate) {Shared Datum StartDate; Shared Datum Enddate;}Gemäß dem Typ -System ist der Anrufer verpflichtet, den DateFormaterror zu verarbeiten:
Wert P = Parseperiod (Start, Ende); if (ist DateFormaterror p) {...} else {...}Oder, wenn uns das tatsächliche Problem mit einem bestimmten Datumsformat (was möglich ist, vorausgesetzt, der Initialisierungscode, an dem wir arbeiten, fehlen diese Informationen), können wir Null anstelle von DatumFormaterror verwenden:
// gibt NULL zurück, wenn die angegebene Zeichenfolge // kein gültiges datiertes Datum darstellt? ParseDate (String -Datum) => ...; gemeinsame Periode? Parseperiod (String Start, String End) => if (existiert startDate = parseDate (start), existiert enddate = ParseDate (Ende)), Zeitraum (Startdate, Enddate) sonst null; freigegebener Klassenperiode (Startdate, Enddate) {Shared Datum StartDate; Shared Datum Enddate;}Der Ansatz zur Verwendung von Fabrikfunktionen ist gelinde gesagt hervorragend, da er im Allgemeinen eine bessere Isolierung zwischen Validierungslogik und Objektinitialisierung aufweist. Dies ist besonders in Ceylon nützlich, wo der Compiler der Objektinitialisierungslogik einige sehr strenge Einschränkungen hinzufügt, um sicherzustellen, dass alle Bereiche des Objekts nur einmal zugewiesen werden.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.