בדיקת קיום מתודה ברובי

טוב את הנושא הבא ידעתי, אבל למה לא לתעד בהמשך לפוסט הקודם.

היות ורובי מתנהגת זהה לכל דבר שמתנהג כמו ברווז (ראו הגדרת duck typing), לא תמיד יש לנו מחלקה שמכילה מתודה מסויימת, אבל בכל זאת היא יכולה לעבור בתור פרמטר, אבל בשביל להיות בטוחים שיש לה את המתודה שאנחנו רוצים להשתמש בה, אנחנו נשתמש במתודה: respond_to? (הסימן שאלה צריך להיות בסוף השם, כאן יש לי בעיה לשים תווי LTR וכו' בבלוג).

השימוש במתודה תתבצע בצורה הבאה:

100.respond_to?(:to_s) # true

100.respond_to?(:foo) # false

כמו שאפשר לראות המתודה מחזריה או true או false בהתאם לשם המתודה שאנחנו מחפשים (ניתן גם להעביר מחרוזת ולא סימול). היות והמתודה to_s קיימת, אז אנחנו נוכל להשתמש בה. אבל המתודה foo אינה קיימת כאשר מדובר במחלקה של מספר שלם (100 הוא מחלקה לכל דבר ועניין), ולכן נקבל חזרה ערך של false.

12 מחשבות על “בדיקת קיום מתודה ברובי

  1. ik_5 מאת

    זו הסיבה שאני מעדיף לא להתווכח כשאומרים לי שהמונח שאני משתמש בו לא נכון.
    בד"כ הסיבה שאני משתמש במונח זה או אחר היא כי הוא מבהיר מה אני מנסה להגיד, ולא בהכרח שהוא מה שמתאים למה שמתרחש באמת.

    למשל:

    class String
    def self.function
    do something
    end
    end

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

  2. Shai

    בד"כ השימוש במונח לא נכון רק מוסיף בלבול, ולא מבהיר שום דבר.

    למשל, אני לא יודע מספיק רובי בשביל להבין איזה סוג של פונקציה בדיוק הגדרת שם. אם תגיד לי "זו פונקציה סטאטית", כשזו לא, אתה מבלבל אותי ואת כל מי שנתקל בזה פעם ראשונה. אם במקום זה תגיד "זו פונקציה רוביליאנית; היא דומה לפונקציה סטאטית ב-Java, אבל לא בדיוק", אז גם העברת את הרעיון, גם נתת לי מושג לחיפוש אם זה באמת מעניין אותי, וגם יצרת רושם שאתה מבין על מה אתה מדבר (אני מקווה שאתה לא באמת מנסה להימנע מזה…).

    (כמובן, את המונח "פונקציה רוביליאנית" המצאתי לצורך הדוגמה; כאמור, אין לי מושג מה זה).

  3. ik_5 מאת

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

    זה ממש לא אומר שזה בסדר או נכון מה שאמרתי, אני רק מנסה להסביר את הכיוון שלי ואת הסיבה שאני משתמש בדברים כמו שאני משתמש בהם.

  4. Shai

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

    אתה באמת חושב שלהגיד "100 הוא מחלקה" זה פחות מאמץ לכותב ויותר ברור — למישהו מחוץ לעולם של pure-OO — מלהגיד "100 הוא אובייקט"? בהקשר הזה, ההערה של מאיר — שמוסיפה דיוק לאמירה נכונה — יכולה להיות הערת-שוליים; ההערה שלי — שמתקנת אמירה לא נכונה — היא לא הערת שוליים, אלא שייכת לטקסט העיקרי.

  5. Shai

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

    אתה באמת חושב שלהגיד "100 הוא מחלקה" זה פחות מאמץ לכותב ויותר ברור — למישהו מחוץ לעולם של pure-OO — מלהגיד "100 הוא אובייקט"? בהקשר הזה, ההערה של מאיר — שמוסיפה דיוק לאמירה נכונה — יכולה להיות הערת-שוליים; ההערה שלי — שמתקנת אמירה לא נכונה — היא לא הערת שוליים, אלא שייכת לטקסט העיקרי.

  6. ik_5 מאת

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

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

  7. Shai

    ושוב החשיבה המעורפלת, ההתעלמות מפרטים רלונטיים לטובת פישוט-לכאורה, מובילה אותך לכתוב דברים לא נכונים.

    ברובי, כמו בפייתון, אתה יכול להוסיף מתודות לאובייקט בודד ולא רק למחלקה (לא באמת ידעתי את זה על רובי, אבל חיפוש לא ארוך גילה לי). respond_to? עובדת ברמת אובייקט, לא ברמת מחלקה — אם הגדרת מתודה ספציפית לאובייקט, היא תגלה אותה (דוגמה בהמשך). כלומר: ההתעקשות שלך לדבר על מחלקה היתה באמת, לגמרי, מיותרת.

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

    הדוגמה הבאה מבוססת על פרזנטציה שהיא כנראה די מוכרת בעולם הרובי (אחד המקומות הראשונים בגוגל) — "10 דברים שכל מתכנת Java צריך לדעת על רובי"; ספציפית, על http://onestepback.org/articles/10things/page025.html

    class Dog
    end

    rover = Dog.new
    fido = Dog.new

    def rover.speak
    puts "Red Rover"
    end

    rover.speak # => "Red Rover"
    fido.speak # => NoMethodError

    rover.respond_to?('speak') # => true
    fido.respond_to?('speak') # => false
    Dog.respond_to?('speak') # => false

  8. ik_5 מאת

    ואתה גם יכול לעשות אחרי שהגדרת כבר את Dog את הדבר הבא:

    class Dog
    def self.speak
    something
    end
    end

    ואז לשניהם זה יתקיים.

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

  9. Shai

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

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

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

כתיבת תגובה

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

הלוגו של WordPress.com

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

תמונת Twitter

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

תמונת Facebook

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

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

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

מתחבר ל-%s