عند تحويل رمز Java إلى رمز Ceylon ، أواجه أحيانًا بعض منشئات فئة Java التي تخلط بين التحقق والتهيئة. دعنا نستخدم مثالًا بسيطًا ولكنه مصطنع لتوضيح ما أريد شرحه.
بعض الرمز السيئ
النظر في فئة جافا التالية. (رجل ، لا تكتب مثل هذا الرمز في المنزل)
فترة الطبقة العامة {startdate date final private ؛ تاريخ النهائي الخاص. // إرجاع NULL إذا كانت السلسلة المحددة // لا تمثل تاريخًا صالحًا تاريخًا خاصًا ، فقد تم تحليلي (تاريخ السلسلة) {...} الفترة العامة (String Start ، String End) {StartDate = parsedate (start) ؛ enddate = parsedate (نهاية) ؛ } boolean public isValid () {return startDate! = null && enddate! = null ؛ } التاريخ العام getStartDate () {if (startDate == NULL) رمي جديد alficalstateException () ؛ العودة ابدأ. } التاريخ العام getendDate () {if (endDate == null) رمي جديد alficalstateException () ؛ إرجاع enddate. }}مهلا ، لقد حذرت ذلك من قبل ، إنه مصطنع. ومع ذلك ، ليس من غير المألوف في الواقع العثور على شيء مثل هذا في رمز Java الفعلي.
المشكلة هنا هي أنه حتى إذا فشل التحقق من معلمات الإدخال (في طريقة التحليل المخفي) ، فستظل نحصل على مثيل فترة. لكن الفترة التي نحصل عليها ليست حالة "صالحة". بالمعنى الدقيق للكلمة ، ماذا أعني؟
حسنًا ، إذا لم يتمكن الكائن من الاستجابة بشكل مفيد لعملية عامة ، فأنا أقول إنها في حالة غير صافية. في هذا المثال ، رمي GetStartDate () و GetendDate () استثناء غير قانوني ، وهي حالة لا أعتقد أنها "ذات معنى".
بالنظر إلى هذا المثال من ناحية أخرى ، عند التصميم ، فشلنا في نوع السلامة هنا. تمثل الاستثناءات غير المقيدة "الفراغ" في نظام النوع. لذلك ، فإن تصميم أفضل من نوع الفترة سيكون عدم استخدام استثناءات غير محددة-في هذا المثال ، لم يتم إلقاء غير قانوني.
(في الواقع ، في الكود الحقيقي ، من المرجح أن أواجه طريقة getStartDate () التي لا تتحقق من NULL ، وبعد هذا السطر من الكود ، سيؤدي إلى استثناء nullpointerxception ، وهو أسوأ.)
يمكننا بسهولة تحويل فئة الفترة المذكورة أعلاه إلى فئة من نموذج Ceylon:
فترة الفئة المشتركة (String Start ، String End) {// إرجاع NULL إذا كانت السلسلة المحددة // لا تمثل تاريخ تاريخ صالح؟ parsedate (تاريخ السلسلة) => ... ؛ قيمة maybestartdate = parsedate (ابدأ) ؛ القيمة ربما enddate = parsedate (نهاية) ؛ boolean المشترك صالح => MaybestartDate موجود && redexenddate ؛ DATE SHARD STARTDATE {Assert (موجود MaybestartDate) ؛ إرجاع Maybestartdate ؛ } date date enddate {Assert (موجود maybestartdate) ؛ إرجاع Maybestartdate ؛ } date date enddate {Assert (موجود ربما enddate) ؛ العودة ربما الوضع. }}بالطبع ، سيواجه هذا الرمز أيضًا نفس المشكلات مثل رمز Java الأصلي. صرخ اثنان من رموز التأكيد علينا ، كانت هناك مشكلة في نوع سلامة الكود.
اجعل رمز Java أفضل
كيف نحسن هذا الرمز في جافا؟ حسنًا ، إليك مثال على استثناءات Java التي تم تحديدها المعقولة جدًا التي يتم حلها! يمكننا تعديل الفترة قليلاً لرمي استثناء محدد من مُنشئه:
فترة الطبقة العامة {startdate date final private ؛ تاريخ النهائي الخاص. // رميات إذا كانت السلسلة المحددة // لا تمثل تاريخًا صالحًا تاريخ خاص (تاريخ السلسلة) يلقي DateFormAtexception {...} الفترة العامة (String Start ، String End) DateFormatexception {StartDate = parsedate (start) ؛ enddate = parsedate (نهاية) ؛ } التاريخ العام getStartDate () {return startDate ؛ } التاريخ العام getendDate () {return endDate ؛ }}الآن ، مع هذا الحل ، لن نحصل على فترة في حالة غير ضيقة. سيتم التعامل مع الرمز الذي يركز على الفترة من قبل المترجم للتعامل مع مدخلات غير صالحة ، والتي ستقوم باستيلاء استثناء DateFormatexception.
جرب {الفترة p = فترة جديدة (ابدأ ، نهاية) ؛ ...} catch (dateFormatexception dfe) {...}هذا استخدام جميل ومثالي وصحيح للاستثناءات التي تم فحصها ، وللأسف ، نادراً ما أرى رمز Java باستخدام استثناءات محددة مثل الاستثناء أعلاه.
اجعل رمز Ceylon أفضل
إذن ماذا عن سيلان؟ ليس لدى Ceylon استثناءات محددة ، لذلك نحتاج إلى إيجاد حل مختلف. عادةً ، في الموقف الذي تسمي فيه Java وظيفة ويلقي استثناءًا محددًا ، يقوم Ceylon باستدعاء الوظيفة وإرجاع نوع الاتحاد. نظرًا لأن تهيئة الفئة لا تُرجع أي نوع باستثناء الفئة نفسها ، فإننا نحتاج إلى استخراج بعض منطق التهيئة/التحقق المختلطة لجعله وظيفة المصنع.
// إرجاع DateFormaterror إذا كانت السلسلة المقدمة // لا تمثل صحة صالحة | dateFormaterror parsedate (تاريخ السلسلة) => ... if (هو dateFormaterror startDate) {return startDate ؛ } القيمة enddate = parsedate (نهاية) ؛ if (هو dateFormaterror enddate) {return endDate ؛ } فترة الإرجاع (startDate ، enddate) ؛} فترة الفئة المشتركة (startDate ، enddate) {shared date startDate ؛ نهاية التاريخ المشترك ؛}وفقًا لنظام النوع ، يلزم المتصل التعامل مع DateFormaterror:
القيمة p = parseperiod (ابدأ ، نهاية) ؛ if (هو dateFormaterror p) {...} آخر {...}أو ، إذا كنا لا نهتم بالمشكلة الفعلية بتنسيق تاريخ معين (وهو أمر ممكن ، على افتراض أن رمز التهيئة الذي نعمل عليه هو فقدان تلك المعلومات) ، يمكننا استخدام NULL بدلاً من DateFormaterror:
// إرجاع NULL إذا كانت السلسلة المعطاة // لا تمثل صحة صافية؟ parsedate (تاريخ السلسلة) => ... ؛ فترة مشتركة؟ parseperiod (String start ، end string) => إذا (موجود startDate = parsedate (start) ، موجود enddate = parsedate (نهاية)) ثم الفترة (startDate ، enddate) null ؛ فترة فئة مشتركة (startDate ، enddate) نهاية التاريخ المشترك ؛}
إن نهج استخدام وظائف المصنع ممتازة على أقل تقدير ، لأنه يتمتع عمومًا بعزلة أفضل بين منطق التحقق من الصحة وتهيئة الكائن. هذا مفيد بشكل خاص في سيلان ، حيث يضيف المترجم بعض القيود الصارمة للغاية إلى منطق تهيئة الكائن لضمان تعيين جميع مناطق الكائن مرة واحدة فقط.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.