Dart Exception Handling
کنترل خطاها و استثنا در دارت Dart Exception Handling
استثنا در زبان دارت هر چیزی غیر از حالت طبیعی است که در بررنامه رخ میدهد. برنامه نویس میتواند استثنا را تشخیص دهد و تحت کنترل خود بگییرد. این عمل را اداره کردن استثنا میگویند.
قابلیت توسعه دارت میتواند انواع و تعداد استثناهایی را که اتفاق می افتند، افزایش دهد. به کمک اداره کننده استثنا هنگامی که استثنایی در برنامه رخ دهد، برنامه بطور خودکار، روال کنترل استثنا را فراخوانی میکند. کد کنترل استثنا به ماهیت و اندازه سیستم های نرم افزار بستگی دارد. در بعضی از سیستم ها، مثل سیستم های تجاری، باید کد کنترل استثنای زیادی وجود داشته باشد.
ابزارهای زیادی برای کنترل استثنا وجود دارد. معمولا کدهای کنترل استثنا در سراسر کد سیستم پراکنده اند. استثناها در جاهایی که اتفاق می افتند، تحت کنترل قرار می گیرند. امتیاز این روش این است که برنامه نویسی که کد را میخواند کنترل استثنا را نیز در نزدیکی آن مشاهده میکند و متوجه میشود که آیا کنترل استثنای مناسبی پیاده سازی شده است یا خیر؟.
مشکل این روش این است که، کد سیستم با پردازش استثنا در هم می آمیزد و از حالت یکنواختی خارج میشود. این کار موجب میشود تا خواندن برنامه جهت پی بردن به صحت کامل آن مشکل شود. علاوه بر این درک ونگهداری کد دشوار خواهد بود.
استثنا های موجود در دارت Dart Exception Handling
در جدول زیر کلاس های استثنا که توسط خود دارت ساخته شده اند را توضیح میدهیم.
توضیحات | استثنا |
این استثنا هنگامی رخ میدهد که در بارگذاری یک کتابخانه مشکلی پیش آید | DeferredLoadException |
این استثنا هنگامی رخ میدهد کهیک رشته یا هر نوع داده دیگری فرمت قابل انتظار را نداشته و نمیتواند پردازش شود | FormatException |
این استثنا هنگامی رخ میدهد که یک عدد بر صفر تقسیم شود | IntegerDivisionByZeroException |
یک کلاس پایه برای تمامی استثنا های ورودی/خروجی | IOException |
این استثنا هنگامی رخ میدهد که یک isolate نتواند ایجاد شود | IsolateSpawnException |
این استثنا هنگامی رخ میدهد که یک زمانبندی برنامه ریزی شده هنگام انتظار برای یک نتیجه غیرهمزمان رخ دهد | Timeout |
بلوک های try / on / catch
بلوک try حاوی قطعه کدی است که ممکن است اجرای آن باعث رخ دادن یک استثنا شود.
اگر نیاز به مشخص کردن نوع استثنا داریم، از بلوک on استفاده میکنیم.
از بلوک catch نیز هنگامی که به شئ استثنا نیاز داریم، استفاده میشود.
بلوک های فوق باید به ترتیبی که نام برده شده اند، پشت سر هم قرار گیرند و هیچ کدی بین بلوک ها نباید قرار گیرد.
1 2 3 4 5 6 7 8 9 | try { // code that might throw an exception } on Exception1 { // code for handling exception } catch Exception2 { // code for handling exception } |
میتوانیم چندین بلوک on و catch داشته باشیم.
مثال: بلوک on
در مثال زیر دو متغیر داریم که بر هم تقسیم میشوند. در بلوک try یکی از متغیر ها بر صفر تقسیم میشود.
بلوک on نیز حاوی کد مدیریت کننده این استثنا است.
1 2 3 4 5 6 7 8 9 10 11 12 | main() { int x = 12; int y = 0; int res; try { res = x ~/ y; } on IntegerDivisionByZeroException { print('Cannot divide by zero'); } } |
خروجی:
1 | Cannot divide by zero |
مثال: بلوک catch
همان مثال بالا را با بلوک catch پیاده سازی میکنیم:
1 2 3 4 5 6 7 8 9 10 11 12 | main() { int x = 12; int y = 0; int res; try { res = x ~/ y; } catch(e) { print(e); } } |
خروجی:
1 | IntegerDivisionByZeroException |
مثال: بلوک های on..catch
در مثال زیر از هر دو بلوک on و catch استفاده میکنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Live Demo main() { int x = 12; int y = 0; int res; try { res = x ~/ y; } on IntegerDivisionByZeroException catch(e) { print(e); } } |
خروجی:
1 | IntegerDivisionByZeroException |
بلوک finally
بلوک finally بدون توجه به اینکه استثنا رخ داده است یا خیر، اجرا میشود.
این بلوک اختیاری بوده و بعد از تمام بلوک های on و catch قرار میگیرد.
مثال:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | main() { int x = 12; int y = 0; int res; try { res = x ~/ y; } on IntegerDivisionByZeroException { print('Cannot divide by zero'); } finally { print('Finally block executed'); } } |
خروجی:
1 2 | Cannot divide by zero Finally block executed |
پرتاب استثنا Dart Exception Handling
از کلمه کلیدی throw برای ایجاد یا پرتاب یک استثنا استفاده میشود.
استثنا پرتاب شده حتما باید مدیریت شود تا برنامه ناگهانی متوقف نشود.
1 | throw new Exception_name() |
مثال:
1 2 3 4 5 6 7 8 9 10 11 12 13 | main() { try { test_age(-2); } catch(e) { print('Age cannot be negative'); } } void test_age(int age) { if(age<0) { throw new FormatException(); } } |
خروجی:
1 | Age cannot be negative |
ساخت Exception سفارشی
تمامی کلاس های استثنا که در بالا استفاده شد، توسط خود زبان دارت ایجاد شده اند و رابط Exception را پیاده سازی کرده اند.
برنامه نویسان نیز میتوانند با ساخت یک کلاس که رابط Exception را پیاده سازی میکند، استثنا های خود را ایجاد کنند.
1 2 3 | class Custom_exception_Name implements Exception { // can contain constructors, variables and methods } |
مثال:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class AmtException implements Exception { String errMsg() => 'Amount should be greater than zero'; } void main() { try { withdraw_amt(-1); } catch(e) { print(e.errMsg()); } finally { print('Ending requested operation.....'); } } void withdraw_amt(int amt) { if (amt <= 0) { throw new AmtException(); } } |
خروجی:
1 2 | Amount should be greater than zero Ending requested operation.... |