5

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

  • Upload
    -

  • View
    705

  • Download
    3

Embed Size (px)

DESCRIPTION

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

Citation preview

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

Methods - מתודות

כל מתודה בג'אווה חייבת להשתייך למחלקה אחת בדיוק, כלומר, לא ייתכן מצב בו מתודה לא שייכת לאף מחלקה ובאותו

האופן, לא ייתכן מצב בו מתודה שייכת ליותר ממחלקה אחת.

המשתייכת למחלקה, משתייכת אליה בכך שהיא הוצהרה והוגדרה בתוך מרחב ההכרה של המחלקה ואין אותה המתודה,

אפשרות כמו בשפות אחרות לבצע הצהרה על המתודה בתוך המחלקה והגדרה מחוצה לה.

getters & setters

מהמשתנים שלנו כמשתנים ע"מ למנוע מצב בו מתבצעת גישה ישירה למשתני המופע שלנו, אנו נעדיף להגדיר כמה שיותר

. עם זאת, אנו כן מעוניינים לאפשר חשיפה של המשתנה לעדכון ולצפייה וזאת בהתאם privateבעלי מציין גישה

מאפשרות לנו גישה ממוסכת למשתני המופע שלנו באופן כזה שהלקוח רואה רק את מה set-ו getלהגדרתנו. מתודות

מה שאנחנו רוצים שישנה ובאופן בו אנו רוצים שישנה אותו. לדוגמה, ניתן לכתוב שאנחנו רוצים שהוא יראה ומשנה רק את

אשר מכילה מסכת קלט ובדיקת נכונות הקלט בטרם ההשמה, ובכך למנוע שגיאות שונות שעלולות לקרות setמתודת

במהלך הדרך, דבר שלא יכול היה להתקיים באם היינו מאפשרים גישה ישירה למשתנה.

: set-ו getת למתודות הגדרה כללי

public class GetnSet { private varType varName; public varType getVarName() { return varName; } public void setVarName(varType varName) { this.varName = varName; } }

נביא דוגמה מעשית לכל אחת מהמתודות הנ"ל:

get() – נניח ובמחלקה שלנוCar קיים משתנה ,price משתנה זה מכיל את מחיר המכונית נטו, כפי שעלתה לסוחר .

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

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

הנוסחה לחישוב -, ולהכניס את הלוגיקהprivateבמשתנה עם מציין גישה priceבמקרים כאלו, נוכל להגדיר את המשתנה

. מתודה זו תחזיר את המחיר, לא לפני שתעשה עליו את המניפולציות ()getPriceבשם publicהמחיר הסופי לתוך מתודה

תו הסוחר.הדרושות עפ"י או

set(varType var) – נמשיך עם אותה הדוגמה, וניקח מקרה בו אנו מעוניינים לאפשר לסוחר להזין את מחיר המכונית. איננו

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

עם setPrice(int price)וניצור מתודה privateהינה priceאן נוודא שהגישה למשתנה עלולות להפיל תכנית שלמה. גם כ

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

.'נקבע רף מקסימום למחיר וכו

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

:()get-ו ()setנראה דוגמה למימוש של המתודות

public class Car { private int price; private int customerPrice; private int customs; private int tax; private int registration; public int getCustoms() { return customs; } public void setCustoms(int customs) { this.customs = customs; } public int getTax() { return tax; } public void setTax(int tax) { this.tax = tax; } public int getRegistration() { return registration; } public void setRegistration(int registration) { this.registration = registration; } private int getRealPrice() { return price; } public void setPrice(int price) { if (price<0) System.out.println("Negative value not allowed!"); else if (price>100000) System.out.println("Can't afford to buy at more than 100,000!"); else { this.price = price; setCustomerPrice(price); } } private void setCustomerPrice(int price) { customerPrice = price+getTax()+getCustoms()+getRegistration(); } public int getPrice() { if (getRealPrice()==0) System.out.println("Price calculated without purchase price"); if (getRegistration()==0) System.out.println("Price calculated without registration fees"); if (getTax()==0) System.out.println("Price calculated without tax amount"); if (getCustoms()==0) System.out.println("Price calculated without customs fees"); return customerPrice; } }

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

כעת נתייחס למעט מהנקודות המעניינות מדוגמת הקוד הנ"ל:

ע"מ למנוע גישה ישירה אליהם. כאמור, באופן כזה, ע"מ לעדכן את ערכו של משתנה יש private -המשתנים כולם הוגדרו כ

שהגדירה חוקיות לגבי הערכים המוזנים, אם יש בכך צורך. setצורך לעבור במתודת

מתוך רצון למנוע הזנה ידנית של מחיר הצרכן private-כ setCustomerPrice ,getRealPriceכמו כן, הוגדרו המתודות

כבר לא של המכונית )מורכב ממס' גורמים(, ורצון למנוע קבלת מידע לגבי מחיר הבסיס של המכונית. מרגע שהוזן, הוא

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

, דבר שלא היה מתאפשר אם היינו מאפשרים גישה -priceמגבילה את טווח הערכים שניתן לקבוע ל setPriceהמתודה

כפי priceולא את ערכו של customerPriceערכו של המשתנה מחזירה בכלל את getPriceישירה למשתנה, והמתודה

שניתן היה אולי לצפות.

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

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

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

אליהם בצורה ישירה מחוץ לגבולות המחלקה.

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

תחזוקת קוד קלה – maintainabilityשמירה על

, עשינו זאת תוך numberנניח שהתוכנית שלנו משתרעת על אלפי שורות קוד ובכל מקום בקוד בו רצינו לדבר על המשתנה

קריאה ישירה בשם המשתנה )הרי אנו נמצאים בתוך הגדרת המחלקה שלנו, ובשל כך, אנו יכולים לפנות למשתנים שהוגדרו

בלי חשש" כל עוד שאנחנו נמצאים בטווח ההכרה של המחלקה שאנו מגדירים זה עתה(."מ private -כ

מבלי למסך שום דבר, ולכן, אם כל מה number, בסה"כ מחזירה את ערכו של המשתנה ()getNumberנניח גם שהמתודה

במקום println(getNumber())שאנחנו רוצים לעשות זה להדפיס למשל את ערכו של המשתנה, נראה כמאמץ מיותר לכתוב

.println(number)פשוט לכתוב

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

להשתמש בשתי הצורות באופן שקול ואם כך הדבר, אז למה לא בדרך המקוצרת הפשוטה יותר...?

ל הנושא שנקרא "תחזוקת קוד":כאן בדיוק הזמן לדבר ע

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

.1, להדפיס את ערכו + numberשאנחנו צריכים בכל פעם שאנו פונים להדפיס את ערכו של

number -ולשנות ל numberיש צורך לגשת לכל מקום בו כתבנו בהתאם להנחות שתיארתי, ע"מ שנוכל להדר את התכנית,

+1.

055-, כך שבמקום שיופיע ב()getNumberפתרון "מיינטיינאבילי" לבעיה זו, יהיה לפנות למשתנה אך ורק דרך אותה מתודת

המשתנה שמחזירה את ערכו של ()getNumberמקומות הקריאה למתודה 055-תופיע ב ,numberמקומות שם המשתנה

number כך שגם במקרה של השינוי הנ"ל, נוכל לבצע אותו בתוך הלוגיקה של ,getNumber() פעם אחת בדיוק, כך שתחזיר

number +1 במקוםnumber .מבלי לשנות דבר בשאר התכנית

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

Static Methods –מתודות סטטיות –מתודות מחלקה

לפני ערך staticהגדרת מתודה סטטית תיעשה בדומה להגדרת המשתנה, לשורת ההגדרה תתווסף המילה השמורה

החזרה של המתודה ואחרי מציין הגישה. באופן הבא:

public static void staticMethod() { }

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

מהמחלקה:

car1.staticMethod(); //Method call via an instance Car.staticMethod(); //Method call via Class name

בכל תכנית. ניתן להריץ את המחלקה כאפליקציה גם אם לא יצרנו אובייקט מאותה mainניתן לראות כדוגמה את המתודה

סטטית! mainהמחלקה. זה מתאפשר לנו הודות להיותה של

, נבחין שאין לנו אפשרות mainמאותן הסיבות שצוינו לעיל, אם נצהיר על משתנה מופע במחלקה בה מוגדרת המתודה

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

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

מבלי תלות באובייקט מסוים.

מתודות סטטיות לא ניתנות לדריסה.

Final Methods –מתודות סופיות

להגדרתה: finalלמתודה ע"י הוספת Overridingת האפשרות לעשות ניתן למנוע א

public final void FinalMethod() { }

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

ובכך שמתודה מוגדרת כסופית, מלבד היתרון הברור )מניעת שינוי אופי פעולת המתודה(, יש גם שיפור ניכר בביצועים, היות

נחסכת הבדיקה בזמן ריצה באיזו גרסה של מתודה יש להשתמש.

Deprecated Methods –מתודות שעבר זמנן

מתודות )או מחלקות( שבעקבות התחדשות של השפה הפכו למיושנות.

זאת ע"י הוספה של בעת שימוש במתודות כאלה תינתן הודעת אזהרה. אם מהדרים דרך שורת הפקודה ניתן לעשות

-deprecation בעת הרצת הפקודהjavac .ולקבל מידע בנושא

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

יעודכן בהתאם. javadoc-גם מסמך ה

.Deprecated-של מתודה שהוגדרה כ Override-לרוב אנו ניתקל במקרים כאלו כאשר ננסה לבצע דריסה