English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
تكون الأعطال مرتبطة دائمًا بالتنفيذ. إذا فتحت ملفًا غير موجود ولم تتعامل مع هذا الحالة بشكل صحيح، فإن برنامجك يعتبر من البرامج منخفضة الجودة.
إذا حدث خطأ، يتوقف البرنامج. تستخدم الأخطاء لمعالجة أنواع مختلفة من الأخطاء، التي قد تحدث أثناء تنفيذ البرنامج، لذا يجب اتخاذ إجراءات مناسبة، حتى لا يتوقف البرنامج بشكل كامل.
يقدم لـ Ruby آلية ممتازة للتعامل مع الأخطاء. يمكننا begin/end أضف إلى الكود المحتمل أن يرفع خطأ في البloc، باستخدام rescue الفقرة تعطي لـ Ruby معرفة أنواع الأخطاء التي يجب التعامل معها بشكل ممتاز.
begin # بداية raise.. # قم برفع الخطأ rescue [ExceptionType = StandardException] # قم بقبض على نوع معين من الأخطاء، القيمة الافتراضية هي StandardException $! # يعبر عن معلومات الخطأ $@ # يعبر عن موقع ظهور الخطأ else # الحالات الأخرى من الأخطاء .. تأكد # مهما كان هناك خطأ أو لا، تدخل إلى هذا الكود end # تنتهي
إلى begin يتم حمايته. rescue كل شيء في rescue و end إلى
من begin كل rescue بعد ذلك، يقوم Ruby بتقارن الاستثناء الذي تم إلقاؤه مع كل من المعامل. إذا كان الاستثناء المسمى في جملة rescue مطابقاً لنوع الاستثناء الحالي أو كان هو فئة استثناء له، فإن التطابق ينجح.
إذا لم يكن الاستثناء مطابقاً لجميع أنواع الأخطاء المحددة، يمكننا في جميع rescue بعد الجملة. else بعد الجملة.
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue file = STDIN end print file, "==", STDIN, "\n"
نتائج الإنتاج في هذا المثال أعلاه. يمكنك رؤية،STDIN تم استبداله file ، لأنفتحفشل.
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
يمكنك استخدام rescue قالب التقاطع يلتقط الاستثناء، ثم يستخدم retry جملة تبدأ من البداية. begin قالب.
begin # الاستثناء الذي يلقاه هذا الكود سيتم التقاطعه من قبل جملة rescue أدناه rescue # هذا القالب سيقوم بالتقاطع مع جميع أنواع الاستثناءات retry # سيقوم هذا بتحويل التحكم إلى بداية begin end
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue fname = "existant_file" retry end
هنا هو مسار المعالجة:
حدث استثناء أثناء الفتح.
الانتقال إلى rescue. يتم تعديلfname.
الانتقال إلى بداية begin من خلال retry.
تم فتح الملف بنجاح هذه المرة.
استمر في العملية الأساسية.
ملاحظة:إذا لم يكن الملف المعدل موجودًا، فإن كود هذا المثال سيحاول بشكل لا نهائي. لذا، يجب أن تكون حذرًا عند استخدام معالجة الاستثناءات. retry.
يمكنك استخدام raise جملة القاء استثناء. يتم القاء هذا الاستثناء من قبل الطريقة في وقت الطلب. سيتم إصدار الرسالة الثانية كجزء من ذلك.
raise أو raise "Error Message" أو raise ExceptionType, "Error Message" أو raise ExceptionType, "Error Message" condition
الشكل الأول ببساطة يعيد القاء الاستثناء الحالي (إذا لم يكن هناك استثناء حالي فيمكنه القاء RuntimeError). يتم استخدام هذا في برنامج معالجة الاستثناءات قبل إدخال الاستثناء.
الشكل الثاني ينشئ استثناءً جديداً RuntimeError استثناء، يضبط رسالته بالشكل المحدد. ثم يُقذف الاستثناء بعد ذلك إلى قائمة التتابع الطلبية.
الشكل الثالث يستخدم المعامل الأول لإنشاء استثناء، ثم يضبط الرسالة المتعلقة بالمعامل الثاني.
النوع الرابع يشبه النوع الثالث، يمكنك إضافة أي جملة شرطية إضافية (مثل}} unless)لتحفيز الاستثناء.
#!/usr/bin/ruby begin puts 'أنا قبل raise.' raise 'An error has occurred.' puts 'أنا بعد raise.' rescue puts 'أنا تم إنجاز الإنجاز.' end puts 'أنا بعد كتلة begin.'
نتائج الإخراج للعينة أعلاه هي:
أنا قبل raise. أنا تم إنجاز الإنجاز. أنا بعد كتلة begin.
عرض آخر raise مثال على الاستخدام:
#!/usr/bin/ruby begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect end
نتائج الإخراج للعينة أعلاه هي:
A test exception. ["main.rb:4"]
في بعض الأحيان، قد تحتاج إلى تأكد من أن بعض العمليات يتم تنفيذها عند انتهاء كتلة الكود. على سبيل المثال، قد تكون قد فتحت ملفًا عند الدخول إلى الكتلة، وعندما تخرج من الكتلة، تحتاج إلى التأكد من إغلاق الملف.
ensure ما تقوم به الجملة هو هذا. يتم وضع ensure بعد آخر rescue ويتضمن كتلة من الأوامر التي يتم تنفيذها دائمًا عند انتهاء الكتلة، بغض النظر عما إذا كانت الكتلة غادرت بشكل طبيعي، أو تم طرد استثناء مع معالجته، أو انتهت بسبب استثناء لم يتم القبض عليه،ensure الكتل دائمًا ما تنفذ.
begin #.. عملية #.. تحفيز استثناء rescue #.. معالجة الأخطاء ensure #.. تأكد من التنفيذ في النهاية #.. هذا سيتم دائمًا تنفيذه end
begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "تأكد من التنفيذ" end
نتائج الإخراج للعينة أعلاه هي:
A test exception. ["main.rb:4"] تأكد من التنفيذ
إذا تم تقديم else جملة، عادة ما يتم وضعها في rescue بعد الجملة، أي ensure من قبل.
else يتم تنفيذ جسم الجملة فقط إذا لم يكن هناك استثناء يُطرح في الجسم الكامل للكود.
begin #.. عملية #.. تحفيز استثناء rescue #.. معالجة الأخطاء else #.. إذا لم يكن هناك استثناء يتم تنفيذ ensure #.. تأكد من التنفيذ في النهاية #.. هذا سيتم دائمًا تنفيذه end
begin # قم بتحفيز 'A test exception.' puts "أنا لا أرفع استثناء" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "تهاني-- لا توجد أخطاء!" ensure puts "تأكد من التنفيذ" end
نتائج الإخراج للعينة أعلاه هي:
أنا لا أرفع استثناء تهاني-- لا توجد أخطاء! تأكد من التنفيذ
يمكن استخدام متغير $! لالتقاط رسائل الأخطاء المطلقة.
يستطيع نظام raise و rescue التخلي عن التنفيذ عند حدوث خطأ، أحيانًا تحتاج إلى الابتعاد عن بنيات تنسيق عميقة عند معالجة الحالات الطبيعية. في هذه الحالة، يأتي دور catch و throw.
catch تم تعريف قالب يستخدم الاسم المحدد (يمكن أن يكون Symbol أو String) كعلامة. سيعمل القالب بشكل طبيعي حتى يواجه throw.
throw :lablename #.. لن يتم تنفيذ هذا catch :lablename do #.. سيتم مطابقة التنفيذ بعد throw end أو throw :lablename condition #.. لن يتم تنفيذ هذا catch :lablename do #.. سيتم مطابقة التنفيذ بعد throw end
في المثال التالي، إذا أدخل المستخدم '!' كرد فعل على أي إشارة، يستخدم throw للإنهاء التفاعل مع المستخدم.
def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Name: ") age = promptAndGet("Age: ") sex = promptAndGet("Sex: ") # .. # معالجة المعلومات end promptAndGet("Name:")
يحتاج البرنامج المذكور أعلاه إلى تفاعل بشري، يمكنك تجربته على جهازك. نتائج التنفيذ في هذا المثال هي:
الاسم: Ruby on Rails العمر: 3 الجنس:! الاسم:Just Ruby
تقوم الفئات والمجموعات القياسية لـ Ruby بطرح استثنائات. تتكون جميع فئات الاستثناء من سلسلة، بما في ذلك Class Exception في القمة. الطبقة التالية تحتوي على سبعة أنواع مختلفة:
Interrupt
NoMemoryError
SignalException
ScriptError
StandardError
SystemExit
Fatal هو استثناء آخر في هذا الطبقة، ولكن معالج Ruby يستخدمه داخليًا فقط.
ScriptError و StandardError بعض الفروع لها، ولكن لا نحتاج إلى معرفة هذه التفاصيل هنا. الأهم من ذلك هو إنشاء فئات استثنائية الخاصة بنا، يجب أن تكون فروع Class Exception أو فروعها.
دعونا نرى مثالاً:
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end
الآن، لنرى المثال التالي، الذي سيستخدم الاستثناء المذكور أعلاه:
File.open(path, "w") do |file| begin # كتابة البيانات... rescue # خطأ يحدث raise FileSaveError.new($!) end end
في هذا السياق، السطر الأكثر أهمية هو raise FileSaveError.new($!)نحن نستخدم raise لتحديد أن الاستثناء قد حدث، ونقوم بتحويله إلى مثال جديد لـ FileSaveError، بسبب استثناء معين قد يؤدي إلى فشل كتابة البيانات.