Presentation is loading. Please wait.

Presentation is loading. Please wait.

תוכנה 1 בשפת Java שיעור מספר 1: מתחילים מחדש

Similar presentations


Presentation on theme: "תוכנה 1 בשפת Java שיעור מספר 1: מתחילים מחדש"— Presentation transcript:

1 תוכנה 1 בשפת Java שיעור מספר 1: מתחילים מחדש
דן הלפרין עמירם יהודאי בית הספר למדעי המחשב אוניברסיטת תל אביב

2 מטרות הקורס עקרונות נשארים, שפות וכלי פיתוח משתנים ומתחלפים
הבנת מתודולוגיות שמסייעות בפיתוח תוכנה בקנה מידה גדול: תכנות מונחה עצמים, תיכון בעזרת חוזים, ביצוע מקסימום בדיקות בזמן קומפילציה, ניהול זיכרון אוטומטי היכרות עם שפת ג'אווה הקניית מיומנויות תכנות היכרות עם כלי פיתוח מתקדמים (Eclipse) עקרונות נשארים, שפות וכלי פיתוח משתנים ומתחלפים תוכנה 1 בשפת Java אוניברסיטת תל אביב תוכנה 1 בשפת Java אוניברסיטת תל אביב 2

3 מוטיבציה Java היא שפה פופולרית בעולם התוכנה כיום
את עקרונות ה-Object Oriented שתלמדו ניתן ליישם בהרבה שפות תכנות מודרניות דומות תוכנה 1 בשפת Java אוניברסיטת תל אביב תוכנה 1 בשפת Java אוניברסיטת תל אביב 3

4 נושאים שהוצגו/תורגלו (חלקית) עד כה
יסודות התכנות בג'אווה: טיפוסים, מזהים, משתנים, ביטויים, השמה, מבני בקרה, פרוצדורות (מתודות). סביבת העבודה: מהדר (קומפילר), מפרש (אינטרפרטר), סביבת פיתוח שלובה. מודל הזכרון של ג'אווה. עקרונות יסוד: מודולריות, מניעת שכפול קוד. לימוד ראשוני של תכנות מונחה עצמים: מחלקות, עצמים, מנשקים. הכרה ושימוש ב eclipse המחלקות String ו StringBuffer הכרת Java Collections נסתמך על הידע שנצבר, אבל נחזור עליו, לא באותו הסדר תוכנה 1 בשפת Java אוניברסיטת תל אביב תוכנה 1 בשפת Java אוניברסיטת תל אביב 4

5 מה בתכנית? מבוא קצר על שפת ג'אוה תכנות מונחה עצמים, מוטיבציה ועקרונות
עצמים ומחלקות בג'אוה העמסה תוכנה 1 בשפת Java אוניברסיטת תל אביב

6 שלום עולם Write Once – Run Anywhere ! compile Run on Solaris
HelloWorld.class HelloWorld.java Run on Windows Run on Solaris Run on Mac Write Once – Run Anywhere ! תוכנה 1 בשפת Java אוניברסיטת תל אביב תוכנה 1 בשפת Java אוניברסיטת תל אביב 6

7 יבילות (portability) מדוע אנו מסתפקים בפורמט "נוח יותר"?
מדוע אין המהדר יוצר קובץ בפורמט התואם בדיוק לחומרת המחשב, וכך היה נחסך בזמן ריצה גם שלב ה"הבנה" של הקוד? זאת מכיוון שאיננו יודעים מראש על איזה מחשב בדיוק תרוץ תוכנית ה- Java שכתבנו תוכניות Java חוצות סביבות cross platform)) סביבה = חומרה + מערכת הפעלה תוכנית שנכתבה והודרה במחשב מסוים, תוכל לרוץ בכל מחשב אשר מותקן בו מפרש ל- Java תוכנה 1 בשפת Java אוניברסיטת תל אביב

8 המכונה המדומה (Java Virtual Machine)
הקובץ המהודר מכיל הוראות ריצה ב"מחשב כללי" – הוא אינו עושה הנחות על ארכיטקטורת המעבד, מערכת ההפעלה, הזיכרון וכו'... עבור כל סביבה (פלטפורמה) נכתב מפרש מיוחד שיודע לבצע את התרגום מהמחשב הכללי, המדומה, למחשב המסוים שעליו מתבצעת הריצה את המפרש לא כותב המתכנת! דבר זה כבר נעשה ע"י ספקי תוכנה שזה תפקידם, עבור רוב סביבות הריצה הנפוצות תוכנה 1 בשפת Java אוניברסיטת תל אביב 8

9 תלות בסביבה (platform specific)
בשפות אחרות (C/C++) אין הדבר כך: שלב הפיתוח שלב הריצה תוכנה 1 בשפת Java אוניברסיטת תל אביב 9

10 עצמאות סביבתית (platform independence)
ב Java תכונה זו אפשרית הודות לרעיון "שפת הביניים" וה JVM הנפרד לכל סביבה שלב הפיתוח שלב הריצה תוכנה 1 בשפת Java אוניברסיטת תל אביב 10

11 "משבר התוכנה" כתיבת תוכנית קטנה אינה משימה קשה
הקושי בהנדסת תוכנה נעוץ בבניית מערכות תוכנה גדולות (1,000,000< שורות קוד), ע"י מספר אנשים הדורשות תחזוקה לאורך זמן רב (כמה שנים) מאז סוף שנות ה-60 של המאה ה-20 ברור לעולם התוכנה, כי בשביל להתגבר על הקושי שבכתיבת מערכות גדולות יש צורך להלביש על שפת התכנות עקרונות פיתוח נכונים אשר ישפרו את היכולת לכתוב מערכות תוכנה מורכבות ידיעת קרוא וכתוב לא הופכת אותך לסופר לימודי ארכיטקטורה לא הופכים אותך לארכיטקט מוצלח תוכנה 1 בשפת Java אוניברסיטת תל אביב

12 תכנות מונחה עצמים אחד מאוספי העקרונות האלה מכונה "תכנות מונחה עצמים" (Object Oriented Programming) שעיקריו (כפי שיבואו לידי ביטוי בקורס): שימוש חוזר בקוד הפשטה מודולריות תיכון בעזרת חוזים (design by contract) ביצוע מקסימום בדיקות תקינות בזמן קומפילציה ניהול זיכרון אוטומטי חלק משפות התכנות המודרניות מקדמות עקרונות אלו ע"י הגדרת מבנים בשפה שיתמכו בהם בצורה ישירה או עקיפה שפת Java היא שפה כזו כשם שלולאת for הוסיפה לתחביר את מרכיבי הלולאה תוכנה 1 בשפת Java אוניברסיטת תל אביב

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

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

15 מודולריות בתכנות מונחה עצמים
בתכנות מונחה עצמים המודולים הם המחלקות מתברר שארכיטקטורת מערכת שמבוססת על הנתונים מאפשרת מודולריות טובה יותר מארכיטקטורה שמבוססת על הפונקציונליות מכיוון שהישויות העיקריות של המערכת נשארות יותר יציבות לאורך חיי המערכת מאשר הפעולות שרוצים שהמערכת תעשה מכאן היתרון של פיתוח תוכנה מונחה עצמים תוכנה 1 בשפת Java אוניברסיטת תל אביב

16 לקוח וספק במערכת תוכנה ספק (supplier) – הוא מי שקוראים לו (לפעמים נקרא גם שרת, server) לקוח (client) הוא מי שקרא לספק או מי שמשתמש בו (לפעמים נקרא גם משתמש, user). דוגמא: public class Two { ... One obj = new One(..); obj.action(..); } public class One { ... public void action(..) { // doing... } בדוגמא זו המחלקה Two היא לקוחה של המחלקה One One היא ספקית של Two יחס בין מחלקות, אבל גם בין שרותים וכו' תוכנה 1 בשפת Java אוניברסיטת תל אביב

17 עצמים ומחלקות עצם (object) הוא יחידת תוכנה שמספקת שירותים (methods) מסוימים ושיש לה בכל נקודת זמן מצב רגעי מסוים (state). מחלקה (class) היא קבוצה של עצמים מאותו סוג, כלומר שמספקים את אותם שירותים באותה צורה העצמים הם מופעים (instances) של המחלקה עצמים שונים מאותה מחלקה נמצאים במצבים רגעיים שונים המחלקה היא הישות הסטטית בקוד המקור העצם הוא הישות הדינמית בזמן הריצה תוכנה 1 בשפת Java אוניברסיטת תל אביב

18 מחלקה הגדרת מחלקה (בינתיים) public class ClassName {
<list of class members> } רכיבי המחלקה: מספר כלשהו של שדות, שרותים (מתודות) ובנאים. קשורים זה לזה (חוזק פנימי גבוה). שדות/שרותי מחלקה (מלת המפתח static) לעומת שדות/שרותי מופע. ניראות ( private או public או ....) השרות המיוחד public static void main(String[] args) תוכנה 1 בשפת Java אוניברסיטת תל אביב

19 שדות/שרותי מופע ושדות/שרותי מחלקה
לכל עצם יש עותק של שדות המופע. ערכי השדות ברגע נתון מהווים את מצבו של העצם. שרותי מופע פועלים על עצם. שדות מחלקה (מוגדרים עם מילת המפתח static) משותפים לכל העצמים של המחלקה. הם קיימים גם כאשר לא קיים אף עצם מופע של המחלקה. שרותי מחלקה (מוגדרים עם מילת המפתח static) אינם מתייחסים לעצם מסויים. תוכנה 1 בשפת Java אוניברסיטת תל אביב

20 נראות כותב המחלקה קובע איפה ניתן לראות (ולגשת) לרכיבים השונים של המחלקה. public ידוע מחוץ למחלקה – לשימוש על ידי הלקוח private מוכר רק בתוך המחלקה (בהמשך נראה אפשרויות נוספות) הלקוח צריך לדעת רק את השרותים שמיועדים לו; השדות משמשים למימוש, ולכן יהיו בדרך כלל פרטיים לעתים יהיו גם שרותים פרטיים – מספקים שרות לשרותים אחרים במחלקה, אך לא ללקוח כך מקטינים את הצימוד שינוי במימוש (שינוי הייצוג, שינוי אלגוריתם של שרות) אינם משפיעים על הלקוח תוכנה 1 בשפת Java אוניברסיטת תל אביב

21 הגדרת שרות התחביר של הגדרת שרות הוא:
<modifiers> <type> <method-name> ( <paramlist> ) { <statements> } <modifiers> הם 0 או יותר מילות מפתח מופרדות ברווחים (למשל public static) <type> מציין את טיפוס הערך שהשרות מחזיר void מציין שהשרות אינו מחזיר ערך <paramlist> רשימת הפרמטרים הפורמליים, מופרדים בפסיק, כל אחד מורכב מטיפוס הפרמטר ושמו תוכנה 1 בשפת Java אוניברסיטת תל אביב

22 דוגמא – מחלקה פשוטה שדות מופע פרטיים שדה מחלקה פרטי בנאי
public class Pair { private int val; private Pair next; static private int count = 0; public Pair(int v, Pair n) { val = v; next = n; count++; } public int value () { return val; שדות מופע פרטיים שדה מחלקה פרטי בנאי שרות מופע מיוצא תוכנה 1 בשפת Java אוניברסיטת תל אביב

23 המשך דוגמא public Pair nextPair ( ) { return next; }
public void changeVal(int v) { val = v; public static int howMany ( ) { return count; תוכנה 1 בשפת Java אוניברסיטת תל אביב

24 דוגמת שימוש מה הפלט? public class TestPairs {
public static void main(String[] args) { Pair one = new Pair(1,null); Pair two = new Pair(2,one); one = new Pair(3,new Pair(4,one)); System.out.println(Pair.howMany() + " pairs created"); for (Pair tmp = one; tmp != null; tmp = tmp.nextPair()) { System.out.print(tmp.value() + " "); } System.out.println(); מה הפלט? 4 pairs created 3 4 1 תוכנה 1 בשפת Java אוניברסיטת תל אביב

25 הערות לדוגמה הלקוח (במקרה זה המחלקה TestPairs) יכול לקרוא לשרותים המיוצאים, ואינו יכול לגשת לשדות הפרטיים. הלקוח יכול גם להפעיל את הבנאי כדי ליצור עצמים. קריאה לשרות מחלקה בתחביר <ClassName>.<method>(<parameters>) לדוגמא Pair.howMany( ) קריאה לשרות מופע בתחביר <Target>.<method>(<parameters>) לדוגמא tmp.nextPair( ) כאשר <Target> הוא משתנה (או כל ביטוי) שהוא התייחסות לעצם מהטיפוס המתאים – יעד הקריאה תוכנה 1 בשפת Java אוניברסיטת תל אביב

26 פניה לעצם המוצבע (dereference)
ב tmp.nextPair( ) השתמשנו באופרטור '.' (הנקודה) שאפשר גישה לעצם המוצבע (dereference) כך קוראים לשרות מיוצא של העצם באופן דומה נגשים לשדה מיוצא של העצם <Target>.<field> קריאה לשרות (או גישה לשדה) ללא יעד – כלומר <method>(<parameters>) משמעותה היא התייחסות לעצם הנוכחי, כלומר כאילו נכתב this.<method>(<parameters>) כך גם לגבי גישה לשדה קריאה לשרות (או גישה לשדה) בעצם הנוכחי לא דורשת שהוא יהיה מיוצא תוכנה 1 בשפת Java אוניברסיטת תל אביב

27 גוף השרות גוף השרות מכיל הצהרות על משתנים מקומיים (variable declaration) ופסוקים ברי ביצוע (כולל return) משתנים מקומיים נקראים גם משתנים זמניים, משתני מחסנית או משתנים אוטומטיים הצהרות יכולות להכיל פסוק איתחול בר ביצוע (ולא רק אתחול ע"י ליטרלים) public void doSomething(String str) { int length = str.length(); ... הגדרת משתנה מקומי צריכה להקדים את השימוש בו תחום הקיום של המשתנה הוא גוף השרות חייבים לאתחל או לשים ערך באופן מפורש במשתנה לפני השימוש בו בניגוד לשדות (מופע או מחלקה) שעבורם יש אתחול לערך ברירת מחדל! תוכנה 1 בשפת Java אוניברסיטת תל אביב

28 גוף השרות גוף השרות יכול להתייחס למשתנים מקומיים וגם לשדות של המחלקה.
שרות מופע רשאי להתייחס הן לשדות מופע (של העצם הנוכחי) והן לשדות מחלקה. שרות מחלקה רשאי להתייחס רק לשדות מחלקה ולא לשדות מופע. מדוע? תוכנה 1 בשפת Java אוניברסיטת תל אביב

29 יש צורך באתחול מפורש קטע הקוד הבא, לדוגמא, אינו עובר קומפילציה: int i;
int one = 1; if (one == 1) i = 0; System.out.println("i=" + i); הקומפיילר צועק ש- i עלול שלא להיות מאותחל לפני השימוש בו תוכנה 1 בשפת Java אוניברסיטת תל אביב

30 החזרת ערך משרות ומשפט return
return <optional-expression>; ביצוע משפט return מחשב את הביטוי (אם הופיע), מסיים את השרות המתבצע כרגע וחוזר לנקודת הקריאה אם המשפט כולל ביטוי ערך מוחזר, ערכו הוא הערך שהקריאה לשרות תחזיר לקורא טיפוס הביטוי צריך להיות תואם לטיפוס הערך המוחזר של השרות אם טיפוס הערך המוחזר מהשרות הוא void , משפט ה- return לא יכלול ביטוי, או שלא יופיע משפט return כלל, והשרות יסתיים כאשר הביצוע יגיע לסופו תוכנה 1 בשפת Java אוניברסיטת תל אביב

31 דוגמא לשרות המחזיר ערך public int total(int [] arr) { int sum = 0;
for (int i : arr) { sum += i; } return sum; אם שרות מחזיר ערך, כל המסלולים האפשריים של אותו שרות (flows) צריכים להחזיר ערך איך נתקן את השרות הבא: public int returnZero() { int one = 1; int two = 2; if (two > one) return 0; תוכנה 1 בשפת Java אוניברסיטת תל אביב

32 קריאה לשרות (method call)
קריאה לשרות (לפעמים מכונה – "זימון מתודה") שאינו מחזיר ערך (טיפוס הערך המוחזר הוא void) תופיע בתור משפט (פקודה), ע"י ציון שמו וסוגריים עם או בלי ארגומנטים קריאה לשרות שמחזיר ערך תופיע בדרך כלל כביטוי (למשל בצד ימין של השמה, כחלק מביטוי גדול יותר, או כארגומנט המועבר בקריאה אחרת לשרות) קריאה לשרות שמחזיר ערך יכולה להופיע בתור משפט, אבל יש בזה טעם רק אם לשרות תוצאי לוואי, כי הערך המוחזר הולך לאיבוד גם אם השרות אינו מקבל ארגומנטים, יש חובה לציין את הסוגריים אחרי שם השרות תוכנה 1 בשפת Java אוניברסיטת תל אביב

33 סוגי שרות ישנם 3 סוגי שירותים (מתודות, פונקציות, פרוצדורות)
שאילתות (queries, accessors) מחזירות ערך ללא שינוי המצב הפנימי כגון: בירור יתרה פקודות (commands, transformers, mutators) מבצעות שינוי במצב הפנימי של העצם כגון: משיכה, הפקדה בנאים (constructors) - טכנית זה אינו שרות! יצירת עצם חדש כגון: יצירת חשבון חדש תוכנה 1 בשפת Java אוניברסיטת תל אביב

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

35 יצירת עצם הלקוח יוצר עצם ממחלקה C ע"י הביטוי
new C (<parameters>) הביטוי יכול להופיע בכל מקום בו מצפים לעצם כזה: בצד ימין של השמה או אתחול, כפרמטר בקריאה, וכו' לחישוב הביטוי שני שלבים: ראשית מוקצה גוש זיכרון שכולל בתוכו את כל שדות המופע של המחלקה, ואתחול לערכי ברירת המחדל על פי הטיפוס של כל שדה (0 , 0.0 , false לטיפוסים פרימיטיביים, null להתייחסויות) השלב השני הוא אופציונלי, אם למחלקה נכתב בנאי. תוכנה 1 בשפת Java אוניברסיטת תל אביב

36 בנאי כאמור, מחלקה אינה חייבת להגדיר בנאי. אם אין בנאי, כל עצם שנוצר, שדותיו יאותחלו לערכי המחדל בנאי הוא פונקצית אתחול הנקראת ע"י אופרטור ה new מיד אחרי שהוקצה מקום לעצם החדש. התחביר של הגדרת בנאי דומה להגדרת שרות, אבל לא מופיע טיפוס השם הוא כשם המחלקה בין ה <modifiers> לא יכול להיות static <modifiers> <class-name> ( <paramlist> ) { <statements> } תוכנה 1 בשפת Java אוניברסיטת תל אביב

37 לקוח וספק - שוב הספק והלקוח עשויים להיכתב בזמנים שונים, במקומות שונים וע"י אנשים שונים ואז, כמו בדוגמא, לא יופיעו באותו קובץ (באותה מחלקה) חלק נכבד בתעשיית התוכנה עוסק בכתיבת ספריות – מחלקות המכילות אוסף שרותים שימושיים בנושא מסוים כותב הספרייה נתפס כספק שרותים בתחום (domain) מסוים לדוגמא: Java Collections אוסף של מחלקות למבני נתונים שונים. תוכנה 1 בשפת Java אוניברסיטת תל אביב

38 המחלקה כספריה של שרותים
ניתן לראות במחלקה ספריה של שרותים: אוסף של פונקציות עם מכנה משותף המחלקות ב Java Collections כמו רוב המחלקות ב Java, משמשות כטיפוס נתונים. ואולם קיימות ב- Java גם כמה מחלקות המשמשות כספריות בלבד. אלה מחלקות שיש להן רק שרותי מחלקה. בין השימושיות שבהן: java.lang.Math java.util.Arrays java.lang.System תוכנה 1 בשפת Java אוניברסיטת תל אביב

39 שם מלא (qualified name)
אם אנו רוצים לקרוא לשרות או שדה מתוך שרות של מחלקה אחרת (למשל main), יש להשתמש בשמו המלא של השרות שם מלא כולל את שם המחלקה שבה הוגדר השרות ואחריו נקודה לדוגמא System.out.println("Hello” ); out הוא שדה (מיוצא) במחלקה System תוכנה 1 בשפת Java אוניברסיטת תל אביב

40 שם מלא (qualified name)
במחלקה המגדירה ניתן להשתמש בשם המלא של השרות, או במזהה הפונקציה בלבד (unqualified name) בצורה זו ניתן להגדיר במחלקות שונות פונקציות עם אותו השם (מכיוון שהשם המלא שלהן שונה אין התלבטות – no ambiguity) public class CallingFromAnotherClass { public static void main(String[] args) { MethodCallExamples.printMultipleTimes("Hello", 5); int[] primes = { 2, 3, 5, 7, 11 }; System.out.println("Sum of primes is: " + MethodCallExamples.arraySum(primes)); } בדוגמא הזאת אלו שרותי מחלקה ממש כפי שיכולים להיות לי שני קבצים בשם grades.txt בתיקיות שונות תוכנה 1 בשפת Java אוניברסיטת תל אביב

41 מה קורה בזמן ריצה? כפי שאמרנו, עצמים הם הישויות הדינמיות בזמן ריצה.
נתייחס כרגע לתכנית שאין בה שרותי מחלקה (למעט המתודה main של המחלקה הראשונה). בכל רגע בזמן ריצה קיימים מספר (אולי גדול מאד) של עצמים. אחד מהם הוא "העצם הנוכחי" ומתבצע עליו שרות מסוים. השרות יכול ליצור עצם חדש ממחלקה כלשהי (הפעלת בנאי). השרות יכול לקרוא לשרות אחר (על אותו עצם או על עצם אחר – במקרה זה משתנה העצם הנוכחי). כשהשרות מסתיים, חוזרים לשרות שקרא לו, והעצם שהיה נוכחי. כאשר התכנית מתחילה להתבצע, עדיין אין עצמים, ומתחילה להתבצע המתודה main של המחלקה הראשונה. תוכנה 1 בשפת Java אוניברסיטת תל אביב

42 העמסת שרותים (method overloading)
לשתי פונקציות ב Java יכול להיות אותו שם (מזהה) גם אם הן באותה מחלקה, ובתנאי שהחתימה שלהן שונה כלומר הם שונות בטיפוס ו\או מספר הארגומנטים שלהם לא כולל ערך מוחזר! הגדרת שתי פונקציות באותו שם ובאותה מחלקה נקראת העמסה כבר השתמשנו בפונקציה מועמסת – println עבדה גם כשהעברנו לה משתנה פרימיטיבי וגם כשהעברנו לה מחרוזת נציג שלוש סיבות לשימוש בתכונת ההעמסה נוחות ערכי ברירת מחדל לארגומנטים תאימות אחורה תוכנה 1 בשפת Java אוניברסיטת תל אביב

43 העמסת פונקציות (שיקולי נוחות)
נממש את max המקבלת שני ארגומנטים ומחזירה את הגדול מביניהם ללא שימוש בתכונת ההעמסה (בשפת C למשל) היה צורך להמציא שם נפרד עבור כל אחת מהמתודות: public class MyUtils { public static double max_double(double x, double y) { ... } public static long max_long(long x, long y) } השמות מלאכותיים ולא נוחים תוכנה 1 בשפת Java אוניברסיטת תל אביב

44 העמסת פונקציות (פחות נוחות)
בעזרת מנגנון ההעמסה ניתן להגדיר: public static double max(double x, double y) public static long max(long x, long y) בחלק מהמקרים, אנו משלמים על הנוחות הזו באי בהירות למשל, איזו מהפונקציות תופעל במקרים הבאים: max(1L , 1L); max(1.0 , 1.0); max(1L , 1.0); max(1 , 1); // max(long,long) // max(double,double) // max(double,double) // max(long,long) תוכנה 1 בשפת Java אוניברסיטת תל אביב

45 העמסה והקומפיילר המהדר מנסה למצוא את הגרסה המתאימה ביותר עבור כל קריאה לפונקציה על פי טיפוסי הארגומנטים של הקריאה אם אין התאמה מדויקת לאף אחת מחתימות השרותים הקיימים, המהדר מנסה המרות (casting) שאינן מאבדות מידע אם לא נמצאת התאמה או שנמצאות שתי התאמות "באותה רמת סבירות" או שפרמטרים שונים מתאימים לפונקציות שונות המהדר מודיע על אי בהירות (ambiguity) תוכנה 1 בשפת Java אוניברסיטת תל אביב

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

47 העמסה וערכי ברירת מחדל לארגומנטים
לדוגמא: פונקציה לביצוע ניסוי פיזיקלי מורכב: public static void doExperiment(double altitude, double presure, double volume, double mass){ ... } אם ברוב הניסויים המתבצעים הגובה, הלחץ והנפח אינם משתנים, יהיה זה מסורבל לציין אותם בכל קריאה לפונקציה לשם כך, נגדיר עוד גרסה יותר קומפקטית המקבלת כארגומנט רק את המסה: public static void doExperiment(double mass){ תוכנה 1 בשפת Java אוניברסיטת תל אביב

48 העמסה ותאימות לאחור נניח כי כתבת את הפונקציה השימושית :
public static int compute(int x) המבצעת חישוב כלשהו על הארגומנט x לאחר זמן מה, כאשר הקוד כבר בשימוש במערכת (גם מתוך מחלקות אחרות שלא אתה כתבת), עלה הצורך לבצע חישוב זה גם בבסיסי ספירה אחרים (החישוב המקורי בוצע בבסיס עשרוני) בשלב זה לא ניתן להחליף את חתימת הפונקציה להיות: public static int compute(int x, int base) מכיוון שקטעי הקוד המשתמשים בפונקציה יפסיקו להתקמפל תוכנה 1 בשפת Java אוניברסיטת תל אביב

49 העמסה, תאימות לאחור ושכפול קוד
על כן במקום להחליף את חתימת השרות נוסיף פונקציה חדשה כגירסה מועמסת משתמשי הפונקציה המקורית לא נפגעים משתמשים חדשים יכולים לבחור האם לקרוא לפונקציה המקורית או לגרסה החדשה ע"י העברת מספר ארגומנטים מתאים בעיה – קיים דמיון רב בין המימושים של הגרסאות המועמסות השונות (גוף המתודות compute) דמיון רב מדי - שכפול קוד זה הינו בעייתי מכמה סיבות שנציין מיד תוכנה 1 בשפת Java אוניברסיטת תל אביב

50 הנורא ביותר בעולם (התוכנה) !
שכפול קוד הוא הדבר הנורא ביותר בעולם (התוכנה) ! תוכנה 1 בשפת Java אוניברסיטת תל אביב

51 העמסה, שכפול קוד ועקביות
חסרונות שכפול קוד: קוד שמופיע פעמיים, יש לתחזק פעמיים – כל שינוי, שדרוג או תיקון עתידי יש לבצע בצורה עקבית בכל המקומות שבהם מופיע אותו קטע הקוד כדי לשמור על עקביות שתי הגרסאות של compute נממש את הגרסה הישנה בעזרת הגרסה החדשה: public static int compute(int x, int base){ // complex calcultion... } public static int compute(int x){ return compute(x, 10); תוכנה 1 בשפת Java אוניברסיטת תל אביב

52 העמסת מספר כלשהו של ארגומנטים
ב Java5 התווסף תחביר להגדרת שרות עם מספר לא ידוע של ארגומנטים (vararg) נניח שברצוננו לכתוב פונקציה שמחזירה את ממוצע הארגומנטים שקיבלה: public static double average(double x){ return x; } public static double average(double x1, double x2){ return (x1 + x2) / 2; public static double average(double x1, double x2, double x3){ return (x1 + x2 + x3) / 3; למימוש 2 חסרונות: שכפול קוד לא תומך בממוצע של 4 ארגומנטים תוכנה 1 בשפת Java אוניברסיטת תל אביב

53 העמסת מספר כלשהו של ארגומנטים
רעיון: הארגומנטים יועברו כמערך public static double average(double [] args) { double sum = 0.0; for (double d : args) { sum += d; } return sum / args.length; יתרון: שכפול הקוד נפתר חסרון: הכבדה על הלקוח - כדי לקרוא לפונקציה יש ליצור מערך public static void main(String[] args) { double [] arr = {1.0, 2.0, 3.0}; System.out.println("Average is:" + average(arr)); תוכנה 1 בשפת Java אוניברסיטת תל אביב

54 ג'אווה באה לעזרה תחביר מיוחד של שלוש נקודות (...) יוצר את המערך מאחורי הקלעים: public static double average(double ... args) { double sum = 0.0; for (double d : args) { sum += d; } return sum / args.length; ניתן כעת להעביר לשרות מערך או ארגומנטים בודדים: double [] arr = {1.0, 2.0, 3.0}; System.out.println("Average is:" + average(arr)); System.out.println("Average is:" + average(1.0, 2.0, 3.0)); הדוגמאות להעמסה היו שרותי מחלקה, אבל זה רלבנטי גם לשרותי מופע ובנאים תוכנה 1 בשפת Java אוניברסיטת תל אביב

55 שדות מחלקה לעומת משתנים מקומיים
שדות מחלקה שונים ממשתנים מקומיים בכמה מאפיינים: תחום הכרות: מוכרים בכל הקוד (ולא רק מתוך פונקציה מסוימת) משך קיום: אותו עותק של משתנה נוצר בזמן טעינת הקוד לזיכרון ונשאר קיים בזיכרון התוכנית כל עוד המחלקה בשימוש אתחול: משתנים גלובליים מאותחלים בעת יצירתם. אם המתכנת לא הגדיר להם ערך אתחול - יאותחלו לערך ברירת המחדל לפי טיפוסם (0, false, null) הקצאת זיכרון: הזיכרון המוקצה להם נמצא באזור ה Heap (ולא באזור ה- Stack). שדות מחלקה נקראים גם משתנים גלובליים (global variables), אברי מחלקה (class members), משתני מחלקה (class fields), מאפייני מחלקה (class properties/attributes), שדות סטטיים (static fields/members) דוגמת שימוש שראינו: כמה עצמים מהמחלקה נוצרו? תוכנה 1 בשפת Java אוניברסיטת תל אביב

56 זה סופי ניתן לקבע ערך של משתנה ע"י ציון המשתנה כ final
דוגמא: public final static long uniqueID = ++counter; מוסכמה מקובלת היא שמות משתנים המציינים קבועים ב- UPPERCASE כגון: public final static double FOOT = ; public final static double PI = ; תוכנה 1 בשפת Java אוניברסיטת תל אביב

57 טיפוסים בשפת Java בג'אווה יש שתי משפחות של טיפוסים, ובהתאם לכך שני סוגי משתנים: הטיפוסים היסודיים – 8 טיפוסים שהם חלק משפת התכנות byte, short, int, long float, double,char, boolean טיפוסי הפנייה – למערכים ומחלקות קשירת טיפוסים חזקה (strong typing) תוכנה 1 בשפת Java אוניברסיטת תל אביב 57

58 משפטים וביטויים משפט (statement) מבצע פעולה
כגון: משפט השמה, משפט תנאי, משפט לולאה, קריאה לפונקציה שאינה מחזירה ערך (void) ביטוי (expression) הוא מבנה תחבירי שניתן לחשב את ערכו כגון: הפעלת אופרטור, קריאה לפונקציה המחזירה ערך, משפט השמה פונקציות ב-Java (מתודות) הן סדרה של משפטים משפט מבצע פעולה על ביטויים (expression) ההפרדה אינה מלאה - ישנם משפטים אשר ניתן לחשב את ערכם (כגון משפט השמה, או אופרטור הקידום) תוכנה 1 בשפת Java אוניברסיטת תל אביב

59 משתנים שאינם יסודיים (non primitive variables)
פרט ל-8 הטיפוסים שסקרנו עד כה, כל שאר הטיפוסים ב Java אינם פרימיטיבים הספריה התקנית של Java מכילה יותר מ טיפוסים (!) ואנו כמתכנתים נשתמש בהם ואף ניצור טיפוסים חדשים מערכים ומחרוזות אינם טיפוסים יסודיים משתנה מטיפוס שאינו יסודי נקרא הפנייה (reference type) לעיתים נשתמש בכינויים שקולים כגון: התייחסות, מצביע, מחוון, פוינטר בשפות אחרות (למשל C++) יש הבדל בין המונחים השונים, אולם ב Java כולם מתייחסים למשתנה שאינו יסודי תוכנה 1 בשפת Java אוניברסיטת תל אביב

60 שיתוף (sharing, aliasing)
אם שתי הפניות מצביעות לאותו עצם, העצם הוא משותף לשתיהן. אין עותק נפרד לכל הפנייה כל אחת מההפניות יכולה לשנות את העצם המשותף המוצבע בצורה בלתי תלויה int [] arr1 = {1,2,3}; int [] arr2 = arr1; arr2[0] = 10; System.out.println(arr1[0]); 10 1 arr1 2 100,014 350,000 3 350,000 arr2 // מה יודפס ? 100,018 350,000 תוכנה 1 בשפת Java אוניברסיטת תל אביב

61 הפרוטקציה של מערכים ומחרוזות
מכיוון שמחרוזות ומערכים הם טיפוסים מאוד שכיחים ושימושיים בשפה, הם קיבלו "יחס מועדף", שתי תכונות שאין לאף טיפוס אחר בשפה: פטור מ- new לא ניתן ב Java לייצר עצם ללא שימוש מפורש באופרטור new אבל ניתן ליצור עצם מחרוזת ע"י שימוש בסימן המרכאות ("hello"), ניתן ליצור עצם מערך ע"י שימוש במסולסליים ({1,2,3}) הפניות ואופרטורים על משתנה מטיפוס הפניה אפשר לבצע רק השמה (אופרטור '='), השוואה (אופרטור '==') או גישה לעצם (אופרטור '.') על מערך ניתן גם לבצע גישה לאיבר ([ ]), על מחרוזת ניתן לבצע גם שרשור (+) תוכנה 1 בשפת Java אוניברסיטת תל אביב


Download ppt "תוכנה 1 בשפת Java שיעור מספר 1: מתחילים מחדש"

Similar presentations


Ads by Google