זריקת חריגה (חלק שלישי)

בחלק הקודם הצגתי בעודף פשטות כיצד ניתן לתפוס חריגה. כמובן שיש הרבה מעבר למה שהצגתי, אבל אתעסק איתם רק בהמשך של הסדרה. עכשיו אנסה בצורה פשוטה להציג כיצד ניתן לזרוק את החריגה.

ברובי ישנם 2 מתודות המגיעות ממודל Kernel אשר מאפשרות לזרוק חריגות. 2 המתודות זהות לחלוטין, למעט השם שלהן:

  • raise
  • fail

אתם בטח רוצים לדעת מתי להשתמש באיזו מתודה, ובכן זה תלוי בכם. אישית אני חושב ש fail צריך להיות בשימוש כאשר אנחנו רוצים לדווח על משהו שנכשל, בעוד ש raise כאשר אנחנו רוצים להרים הלאה את החריגה, למשל לא הצלחנו לטפל בה כראוי, או שתפסנו אותה, אבל אנחנו לא באמת יודעים לטפל בה.

המתודות יכולות לקבל עד 3 פרמטרים (רק הפרמטר הראשון הוא חובה):

  1. מחלקה של החריגה שאותה רוצים "לזרוק"
  2. מחרוזת שרוצים להציג
  3. את ה stack שרוצים להציג, בשביל להראות מאיפה התרחשה החריגה

התחביר המינימאלי שנראה הוא כזה:

raise ArgumentError

ותחביר בשימוש מלא יראה בצורה הבאה:

raise ArgumentError, 'Wrong amount of parameters supplied', caller

caller הוא מערך שמכיל את ה stack של הקריאות שלנו עד לנקודה הנוכחית (כולל).

כאשר יש חריגה, היא מאתחלת ערך של משתנה גלובלי בשם:

$!

אשר מכיל את מופע המחלקה (instrace) של החריגה אשר הורמה. אם אתם לא אוהבים את הגישה של שפת Perl אשר נראת כאן (שפת רובי גם מושפעת משפת Perl), ניתן להשתמש בEnglish שמגיע עם רובי, אשר יוצר משתנה גלובלי בשם ERROR_INFO$ שהוא כינוי למשתנה !$ בצורה קריאה יותר. כלומר:

require 'English'
puts $ERROR_INFO.message
puts $!.message

יציגו את אותה ההודעה בדיוק.

חשוב להבין ש"הרמת" חריגה ברובי, אינה חלק מתחביר השפה, אלא מימוש בתוך השפה. כך ש"בזכות" העובדה שraise ו fail שייכים למודול Kernel, ניתן לשכתב אותם גם לעשות משהו אחר לגמרי כאשר צריך להרים חריגה. העניין הוא שיש מצב בו השינוי שנעשה לא יתפס, וזה כאשר משתמשים במערכת אשר עושה binding לרובי משפה אחרת כדוגמת שפת C. שם הרמת החריגה נעשת ברמה נמוכה יותר, ואין לנו יכולת לשנות את הפעולה שלה.

4 מחשבות על “זריקת חריגה (חלק שלישי)

  1. ארתיום

    הערות קטנות:

    – האם המשתנה ‎$!‎ הזה הוא גלובלי או "thread-local"? כי אם הוא לגובלי זה מאוד בעייתי. אני מניח שהוא קשור לחוט הנוכחי או מחסנית (כמו שזה ב־C++‎) תוכל לענות על זה.
    – ב־C אין חריגות – exceptions. יש אותן רק ב־C++‎.

    1. ik_5 מאת

      אני אקדיש פוסט שלם לנושא של עבודה עם חריגות וthread. יש הרבה יותר דברים שצריך להבין לפני בכלל שנכנסים לקטע הזה.

      בC אין חריגות של השפה, יש חריגות אשר קשורות לרובי כאשר אתה כותב binding או מודול עבור רובי בשפה. יש לך בheader הכתוב ב C של רובי את rb_raise שמעלה את החריגה ואין לך יכולת "לשכתב" אותו בניגוד למה שכתוב ברובי עצמה.

  2. יורם

    כתבת :
    . אם אתם לא אוהבים את הגישה של שפת Perl אשר נראת כאן (שפת רובי גם מושפעת משפת Perl), ניתן להשתמש בEnglish שמגיע עם רובי, אשר יוצר משתנה גלובלי בשם ERROR_INFO$ שהוא כינוי למשתנה !$ בצורה קריאה יותר.
    גם הרעיון של מודול בשם English שנותן שמות קריאים יותר למשתנים האלו מגיע מפרל…
    לשאלתו של ארתיום, לפחות בפרל $! מכיל את הערך של errno, שהוא כשלעצמו thread-local.

  3. פינגבק: בעיות בהתנהגות החריגות (חלק רביעי) | לראות שונה

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s