JavaコードをCeylonコードに変換すると、検証と初期化を混乱させるJavaクラスコンストラクターに遭遇することがあります。簡単だが人工的なコードの例を使用して、説明したいことを説明しましょう。
いくつかの悪いコード
次のJavaクラスを検討してください。 (男、自宅でそのようなコードを書かないでください)
パブリッククラス期間{プライベート最終日開始時期。プライベート最終日の終了。 //指定された文字列が有効な日付を表していない場合にnullを返しますprivate date parsedate(string date){...} public period(string start、string end){startdate = parsedate(start); enddate = parsedate(end); } public boolean isvalid(){return startdate!= null && enddate!= null; } public date getStartDate(){if(startDate == null)throw new IllegalStateException(); startdateを返します。 } public date getEnddate(){if(enddate == null)throw new IllegalStateException(); return enddate; }}ねえ、私は前にそれを警告しました、それは人工です。ただし、実際のJavaコードでこのようなものを見つけることは実際には珍しくありません。
ここでの問題は、入力パラメーターの検証(非表示のparsedate()メソッド)が失敗したとしても、期間のインスタンスを取得することです。しかし、私たちが得る期間は「有効な」状態ではありません。厳密に言えば、どういう意味ですか?
まあ、オブジェクトが公共事業に有意義に応答できない場合、私はそれが非有効な状態にあると言うでしょう。この例では、getStartDate()およびgetEnddate()を違法なexception例外を投げます。これは「意味がある」とは思わない場合です。
一方、この例を見ると、期間を設計するとき、ここでタイプの安全性に失敗しました。チェックされていない例外は、タイプシステムの「ボイド」を表します。したがって、より良い期間タイプセーフデザインは、未確認の例外の非使用です。この例では、IllegalStateExceptionはスローされません。
(実際、実際のコードでは、nullをチェックしないgetStartDate()メソッドに遭遇する可能性が高くなります。このコード行の後、NullPointerexceptionの例外が発生します。
上記の期間クラスをセイロンフォームのクラスに簡単に変換できます。
共有クラス期間(文字列start、string end){//指定された文字列//が有効な日付を表していない場合、nullを返しますか? parsedate(string date)=> ...;値maybestartdate = parsedate(start); value MayceEnddate = parsedate(end);共有Boolean有効=> MayBestArtDateが存在する&& MayceEnddateが存在します。共有日startdate {assert(exists maybestartdate); MayBestArtDateを返します。 }共有日付enddate {assert(exists maybestartdate); MayBestArtDateを返します。 }共有日付enddate {assert(exists muyceenddate); muyeddateを返します。 }}もちろん、このコードは元のJavaコードと同じ問題にも遭遇します。 2つのアサートシンボルが私たちに叫びました。コードのタイプの安全性に問題がありました。
Javaコードをより良くします
Javaでこのコードを改善するにはどうすればよいですか?さて、ここにJavaの批判されたチェックされた例外の例があります。コンストラクターからチェックされた例外をスローするために、期間をわずかに変更できます。
パブリッククラス期間{プライベート最終日開始時期。プライベート最終日の終了。 //指定された文字列が有効な日付を表していない場合、プライベートデートparsedate(string date)dateformatexception {...} public期間(string start、string end)throws dateformatexcection {startdate = parsedate(start); enddate = parsedate(end); } public date getStartDate(){return startDate; } public date getEnddate(){return enddate; }}さて、この解決策を使用して、非検証状態で期間を取得することはありません。期間をインスタンス化するコードは、コンパイラによって処理され、無効な入力を処理します。
try {期間p = new Period(start、end); ...} catch(dateformatexception dfe){...}これは、チェックされた例外の素晴らしく、完璧で正しい使用であり、残念ながら、上記のようなチェックされた例外を使用してJavaコードを見ることはめったにありません。
セイロンコードをより良くします
それで、セイロンはどうですか? Ceylonには例外がチェックされていないため、別のソリューションを見つける必要があります。通常、Javaが関数を呼び出してチェックされた例外をスローする状況では、Ceylonは関数を呼び出し、組合タイプを返します。クラスの初期化はクラス自体以外のタイプを返さないため、複数の初期化/検証ロジックを抽出して、工場の関数にする必要があります。
//指定された//文字列が有効なdatedateを表していない場合、日付FORMATERRORを返します| dateFormaterror parsedate(string date)=> ...;共有期間| dateformaterror parseperiod(string start、string end){value startdate = parsedate(start); if(dateformaterror startdate){return startdate; } value enddate = parsedate(end); if(dateformaterror enddate){return enddate; } return period(startdate、enddate);}共有クラス期間(startdate、enddate){shared date startdate;共有日の終了;}Type Systemによると、発信者はDateFormaterrorを処理する義務があります。
値p = parseperiod(start、end); if(is dateformaterror P){...} else {...}または、指定された日付形式の実際の問題を気にしない場合(これは可能であり、取り組んでいる初期化コードにその情報が欠落していると仮定して)、日付FORMATERORの代わりにnullを使用できます。
//指定された文字列が有効な年代を表していない場合、nullを返しますか? parsedate(string date)=> ...;共有期間? parseperiod(string start、string end)=>> if(exists startdate = parsedate(start)、exists enddate = parsedate(end))then period(startdate、enddate)elsed class period(startdate、enddate){shared date startdate;共有日の終了;}ファクトリ関数を使用するアプローチは、控えめに言っても優れています。これは、一般的に検証ロジックとオブジェクトの初期化の間により良い分離があるためです。これは、Ceylonで特に役立ちます。セイロンでは、コンパイラがオブジェクトの初期化ロジックに非常に厳格な制限を追加して、オブジェクトのすべての領域が1回だけ割り当てられていることを確認します。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。