Transcript Methods

‫תכנות מכוון עצמים ושפת ‪JAVA‬‬
‫הרצאה ‪02‬‬
‫אובייקטים‬
‫‪© Keren Kalif‬‬
‫ביחידה זו נלמד‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫מהו תכנות מכוון עצמים‬
‫מהו אובייקט‬
‫מהי מחלקה‬
‫תכונות ומתודות של מחלקות‬
‫יצירת אובייקט‬
‫תכנות מכוון עצמים בשפת ‪JAVA‬‬
‫‪ ‬הגדרות תכונות ושיטות‬
‫‪ ‬הרשאות גישה‬
‫‪ ‬המחלקה ‪String‬‬
‫‪2‬‬
‫‪© Keren Kalif‬‬
‫תכנות מונחה עצמים‬
‫‪ ‬הבסיס התפיסתי של תכנות מכוון עצמים הוא שכך מאורגן‬
‫העולם‪ :‬בעצמים‬
‫‪ ‬כל דבר הוא אובייקט‪ :‬כסא‪ ,‬שולחן‪ ,‬סטודנט‪ ,‬מרצה וכד'‬
‫‪ ‬לכל אובייקט יש מאפיינים המייצגים אותו‬
‫‪ ‬למשל‪ ,‬לסטודנט יש שם‪ ,‬ת‪.‬ז‪ .‬וממוצע‬
‫‪ ‬לכל אובייקט יש פעולות שהוא יודע לעשות‬
‫‪ ‬למשל‪ ,‬סטודנט יכול לעשות שיעורי בית‪ ,‬ללמוד למבחנים וללכת לים‬
‫‪3‬‬
‫‪© Keren Kalif‬‬
‫העולם מורכב מאובייקטים‬
‫משחק הכדורסל משוחק על ידי שתי קבוצות המתחרות זו בזו‪ .‬מכל‬
‫קבוצה משתתפים במשחק רק ‪ 5‬שחקנים‪ ,‬אך על הספסל יש שחקני‬
‫החלפה נוספים‪ .‬אחד מהשחקנים בכל קבוצה הוא קפטן‪ .‬משחק‬
‫הכדורסל משוחק במשך ‪ 40‬דקות‪ .‬המנצחת במשחק היא הקבוצה‬
‫שקלעה מספר רב יותר של סלים‪.‬‬
‫‪ ‬אובייקטים‪:‬‬
‫‪ ‬משחק כדורסל‬
‫‪ ‬קבוצה‬
‫‪ ‬שחקן‬
‫‪ ‬שחקן קפטן‬
‫‪ ‬ספסל‬
‫‪ ‬סל‬
‫‪4‬‬
‫‪© Keren Kalif‬‬
‫לאובייקטים יש מאפיינים‬
‫‪ ‬נתכנן תוכנת משחק כדורסל‬
‫‪ ‬אחד מהאובייקטים יהיה דריק שארפ‪:‬‬
‫תאריך לידה‪5/10/1971 :‬‬
‫‪1.83‬‬
‫גובה‪:‬‬
‫גארד‬
‫תפקיד‪:‬‬
‫‪5‬‬
‫‪© Keren Kalif‬‬
‫אובייקטים יכולים לעשות דברים ‪ -‬שיטות‬
‫שיטות שהאובייקט דריק שארפ יכול לבצע‪:‬‬
‫לקלוע לסל‬
‫‪6‬‬
‫‪© Keren Kalif‬‬
‫לרדת לספסל‬
‫לכדרר‬
‫האובייקט דריק שארפ ‪ -‬סיכום‬
‫תכונות של האובייקט‬
‫דריק שארפ‪:‬‬
‫תאריך לידה‪5/10/1971 :‬‬
‫‪1.83‬‬
‫גובה‪:‬‬
‫גארד‬
‫תפקיד‪:‬‬
‫שיטות‪:‬‬
‫שיטות שיכול לבצע‬
‫האובייקט דריק שארפ‪:‬‬
‫‪7‬‬
‫‪© Keren Kalif‬‬
‫‪ ‬לקלוע לסל‬
‫‪ ‬לרדת לספסל‬
‫‪ ‬לכדרר‬
‫אובייקטים נוספים דומים‬
‫‪ ‬אובייקטים נוספים של שחקני כדורסל‪:‬‬
‫יניב גרין‪:‬‬
‫תאריך לידה‪16/05/1980 :‬‬
‫‪2.06‬‬
‫גובה‪:‬‬
‫פורוורד‪/‬סנטר‬
‫תפקיד‪:‬‬
‫טל בורשטיין‪:‬‬
‫תאריך לידה‪19/02/1980 :‬‬
‫‪1.98‬‬
‫גובה‪:‬‬
‫גארד‬
‫תפקיד‪:‬‬
‫‪8‬‬
‫‪© Keren Kalif‬‬
‫כל אחד מהם יכול‬
‫גם‪-‬כן לבצע את השיטות‪:‬‬
‫‪ ‬לקלוע לסל‬
‫‪ ‬לרדת לספסל‬
‫‪ ‬לכדררז‬
‫יש כאן מבנה‬
‫‪ ‬יש מספר אובייקטים מאותו טיפוס (שחקן כדורסל)‪ ,‬בעלי תכונות‬
‫זהות‪ ,‬אבל עם ערכים שונים‬
‫תאריך לידה‪19/02/1980 :‬‬
‫‪1.98‬‬
‫גובה‪:‬‬
‫גארד‬
‫תפקיד‪:‬‬
‫תאריך לידה‪5/10/1971 :‬‬
‫‪1.83‬‬
‫גובה‪:‬‬
‫גארד‬
‫תפקיד‪:‬‬
‫‪ ‬אב טיפוס זה נקרא מחלקה (‪)class‬‬
‫‪ ‬בדוגמא זו נקרא למחלקה בשם ‪BasketballPlayer‬‬
‫‪ ‬שימו לב‪ :‬כל שחקן הוא שונה אבל הם כולם אובייקטים של‬
‫המחלקה ‪BasketballPlayer‬‬
‫‪9‬‬
‫‪© Keren Kalif‬‬
‫מהי מחלקה?‬
‫‪ ‬מחלקה היא אבטיפוס לאובייקטים מאותו סוג‬
‫‪ ‬לכל האובייקטים השייכים לאותה מחלקה יש את אותן תכונות‪ ,‬אך‬
‫הם נבדלים בערכי התכונות‬
‫‪ ‬כל האובייקטים מאותה מחלקה יודעים לבצע את אותן פעולות‬
‫‪ ‬אובייקט של המחלקה יודע מה ערכי תכונותיו‬
‫‪ ‬כלומר‪ ,‬אם נשאל את האובייקט "דריק שארפ" מה גובהו‪ ,‬הוא ידע‬
‫לענות (אבל הוא לא ידע מה גובהו של אובייקט "טל בורשטיין")‬
‫‪© Keren Kalif 10‬‬
‫תכונות ושיטות בתכנות מכוון עצמים‬
‫‪ ‬תכונה היא משתנה המהווה נתון מידע כחלק מאובייקט מסוים‬
‫‪ ‬התכונה יכולה להיות מכל טיפוס שלמדנו עד כה (וטיפוסים נוספים)‬
‫‪ ‬שיטה היא אוסף פקודות בשפה לביצוע פעולה בעלת רעיון‬
‫משותף‪ .‬כמו פונקציה‪ ,‬אך משויכת לאובייקט‪.‬‬
‫‪ ‬למשל השיטה ‪ shootBall‬תדמה שהשחקן שהפעיל אותה קולע לסל‬
‫‪ ‬שם השיטה מעיד מה השיטה עושה (הרעיון המשותף של הפקודות)‬
‫‪ ‬אוסף הפעולות בשיטה מעיד על ה"איך" השיטה עושה זאת‬
‫‪© Keren Kalif 11‬‬
)classes( ‫מחלקות‬
)class( ‫מחלקה‬
BasketballPlayer
Attributes:
height
role
birth-date
Methods:
dribble
shootBall
goToBench
‫אובייקט‬
‫מופעים של המחלקה‬
‫אובייקט‬
Yaniv Green
Attributes:
height = 2.06
role
= Center
birth-date = 16/5/1980
Methods:
dribble
shootBall
goToBench
Derick Sharp
Attributes:
height = 1.83
role
= guard
birth-date = 5/10/1971
Methods:
dribble
shootBall
goToBench
© Keren Kalif 12
‫מחלקות (‪ – )classes‬שימו לב‬
‫‪ ‬מחלקה היא דרך מופשטת לתיאור של כל העצמים‬
‫(אובייקטים) מאותו סוג‬
‫‪ ‬עד שלא יצרנו אובייקט של המחלקה‪ ,‬יש לנו רק תיאור מופשט‬
‫(אבטיפוס)‬
‫מחלקה (‪)class‬‬
‫‪© Keren Kalif 13‬‬
‫‪BasketballPlayer‬‬
‫‪Attributes:‬‬
‫‪height‬‬
‫‪role‬‬
‫‪birth-date‬‬
‫‪Methods:‬‬
‫‪dribble‬‬
‫‪shootBall‬‬
‫‪goToBench‬‬
‫שאלה‬
‫‪ ‬הכיסא שאתם יושבים עליו‪ ,‬האם הוא מחלקה או אובייקט?‬
‫‪ ‬והלוח?‬
‫‪ ‬זכרו‪ :‬מחלקה היא רק תאור מופשט!‬
‫‪© Keren Kalif 14‬‬
‫דוגמא ראשונה – המחלקה ‪Clock‬‬
‫‪ ‬כדי לייצר מחלקה חדשה עלינו להוסיף קובץ חדש לפרוייקט‬
‫ששמו יהיה כשם המחלקה‪:‬‬
‫המילה ‪ class‬שמורה בשפה‬
‫ומעידה שזו הגדרה של מחלקה‬
‫‪Clock‬‬
‫‪Attributes:‬‬
‫‪hour‬‬
‫‪minutes‬‬
‫‪Methods:‬‬
‫‪tick‬‬
‫‪addMinutes‬‬
‫‪show‬‬
‫‪© Keren Kalif 15‬‬
‫שם המחלקה‬
‫פה נכתוב את תכונות ושיטות המחלקה‬
‫דוגמא‪ :‬המחלקה ‪Clock‬‬
‫‪‬‬
‫‪‬‬
‫נשים לב שעדיין לא יצרנו אובייקט ממחלקה זו‬
‫בתוך המחלקה אנחנו מגדירים את השיטות‪ ,‬אך עדיין אין בהן שימוש‬
‫התכונות של המחלקה ‪Clock‬‬
‫הן משתנים מטיפוס ‪int‬‬
‫מה השיטות עושות‬
‫‪Clock‬‬
‫‪Attributes:‬‬
‫‪hour‬‬
‫‪minutes‬‬
‫‪Methods:‬‬
‫‪tick‬‬
‫‪addMinutes‬‬
‫‪show‬‬
‫‪© Keren Kalif 16‬‬
‫איך השיטות‬
‫מבצעות את הפעולה‬
‫השימוש במחלקה ‪Clock‬‬
‫‪ ‬יצירת אובייקט מטיפוס ‪ Clock‬תעשה בתוך ה‪ ,main -‬ע"י‬
‫שימוש במילה השמורה ‪new‬‬
‫שם המשתנה‬
‫‪Clock‬‬
‫‪Attributes:‬‬
‫‪hour‬‬
‫‪minutes‬‬
‫‪Methods:‬‬
‫‪tick‬‬
‫‪addMinutes‬‬
‫‪show‬‬
‫‪© Keren Kalif 17‬‬
‫יצירת האובייקט‬
‫מתן ערכים‬
‫לשדות האובייקט‬
‫קריאה לשיטה‬
‫של האובייקט‬
‫שם הטיפוס‬
‫כיצד נראה הזיכרון‬
heap ‫אובייקטים נוצרים בשטח זיכרון הנקרא‬
heap -‫ יש לנו משתנה המכיל את ההפניה לאובייקט שנוצר על ה‬stack -‫ב‬
‫אובייקט בזיכרון מכיל את כל אוסף תכונותיו‬
‫ אין שם‬heap -‫לאובייקט על ה‬
public static void main(String[] args)
Clock c1 = new Clock();
{
hours
c1.hours = 10;
c1.minutes = 8;
10
0
minutes
Clock: c1
NULL




0
8
heap -‫זיכרון ה‬
System.out.print("The time is: ");
c1.show();
System.out.println();
{
© Keren Kalif 18
‫זרימת התוכנית‬
public class Program {
public static void main(String[] args){
Clock c1 = new Clock();
public class Clock
{
public int minutes, hours;
public void tick() {
minutes++;
hours += minutes / 60;
minutes %= 60;
hours %= 24;
}
c1.hours = 10;
c1.minutes = ;8
System.out.print("The time is: ");
c1.show();
System.out.println();
{
{
Clock: c1
NULL
public void show() {
if (hours < 10)
System.out.print("0");
System.out.print(hours + “:”);
hours
10
0
if (minutes < 10)
System.out.print("0");
minutes
0
8
System.out.print(minutes);
}
heap -‫זיכרון ה‬
‫ מדוע לא שמנו הדפסת‬:‫שאלה‬
} // class Clock
?show ‫ בסיום המתודה‬println
© Keren Kalif 19
‫יצירת כמה אובייקטים מהמחלקה‬
public static void main(String[] args) {
Clock c1 = new Clock();
Clock c2 = new Clock();
c1.hours = 10;
c1.minutes = 8;
,‫כאשר פונים לשיטה של אובייקט‬
‫האובייקט מכיר את ערכי תכונותיו‬
c2.hours = 13;
c2.minutes = 45;
hours
{
System.out.print("c1 time is: ");
c1.show();
System.out.print("\nc2 time is: ");
c2.show();
System.out.println(); Clock: c1
Clock: c2
NULL
10
0
minutes
hours
minutes
0
8
13
0
45
0
heap -‫זיכרון ה‬
© Keren Kalif 20
‫הרשאות ‪ private‬ו‪public -‬‬
‫‪ ‬לא נרצה שהתכונות שלנו יהיו חשופות ושכל אחד יוכל לשנות את‬
‫ערכיהן ע"י השמה‬
‫‪ ‬למשל שלא יוכלו לשים בערך של הדקות מספר שאינו בין ‪ 0‬ל‪59 -‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫לכן ניתן לתת הרשאות לתכונות ולשיטות של המחלקה‬
‫תכונה שנרצה לחשוף לשינוי ולצפייה תקבל הרשאת ‪public‬‬
‫תכונה שנרצה שתהייה זמינה לשינוי או צפייה רק בתוך המחלקה‬
‫תקבל הרשאת ‪private‬‬
‫שיטה שנרצה שתהיה לשימוש פנימי של המחלקה נגדיר כ‪-‬‬
‫‪private‬‬
‫‪© Keren Kalif 21‬‬
‫ השינוי בקוד‬- Clock ‫המחלקה‬
:‫עם שינוי ההרשאה נקבל שגיאת קומפילציה‬
class Clock
private
{
int minutes, hours;

public static void main(String[] args) {
Clock c1 = new Clock();
c1.hours = 30;
c1.minutes = 88;
public void tick()
{
minutes++;
hours += minutes / 60;
minutes %= 60;
hours %= 24;
}
System.out.print("The time is: ");
c1.show();
System.out.println();
{
public void show()
{
if (hours < 10)
System.out.print("0");
System.out.print(hours + ":”);
if (minutes < 10)
System.out.print("0");
System.out.print(minutes);
}
} // class Clock
© Keren Kalif 22
‫שימוש בשיטות להשמה ולקבלת ערכים‬
‫תפקידת שיטת ‪ set‬לשים‬
‫ערך בתוך תכונה באובייקט‬
‫תפקידת שיטת ‪ get‬לקבל‬
‫ערך של תכונה באובייקט‬
‫‪© Keren Kalif 23‬‬
‫מימוש שיטות ‪ set‬ו‪get -‬‬
‫אבל עדיין ניתן לשים ערכים לא‬
‫תקינים בתכונות האובייקט!‬
‫‪© Keren Kalif 24‬‬
‫‪'setter‬ים ו‪'getter -‬ים – מימושים מתוקנים‬
‫בתוך ה‪'setter -‬ים באה לידי ביטוי העבודה שהתכונות‬
‫הן ‪ :private‬לא ניתן לשנות אותן ללא בקרה‬
‫‪© Keren Kalif 25‬‬
‫תוצר ההרצה לאחר התיקון‬
‫‪© Keren Kalif 26‬‬
‫וכיצד ה‪ main -‬ידע האם לקלוט נתונים מחדש?‬
‫‪ ‬במימוש הנוכחי בחרנו להדפיס למסך כאשר הקלט שהתקבל אינו‬
‫תקין‬
‫‪ ‬אבל ב‪ main -‬אין לנו דרך לדעת האם פעולת ה‪ set -‬בוצעה‬
‫בהצלחה או האם הושם ערך ברירת המחדל‬
‫‪ ‬לכן נתקן את שיטות ה‪ set -‬כך שיחזירו תשובה מסוג ‪,boolean‬‬
‫כאינדיקציה להצלחה הפעולה‬
‫‪© Keren Kalif 27‬‬
‫ עדכון‬:set ‫השיטות‬
© Keren Kalif 28
main -‫ ב‬set -‫שימוש בשיטות ה‬
© Keren Kalif 29
‫סיכום ‪'set‬ים ו‪'get -‬ים‬
‫‪ ‬כדי לאפשר השמת ערך בתכונה שהיא ‪ ,private‬נכתוב שיטת ‪,set‬‬
‫שהיא ‪ ,public‬המבצעת את פעולת ההשמה‪:‬‬
‫‪ ‬השיטה תקבל כנתון את הערך המבוקש‬
‫‪ ‬השיטה תבצע את בדיקות התקינות על ערך שהתקבל‬
‫‪ ‬לבסוף השיטה תעדכן את הערך המתאים בתכונה‬
‫‪ ‬כדי לאפשר קבלת ערך תכונה שהיא ‪ ,private‬נכתוב שיטת ‪get‬‬
‫שהיא ‪public‬‬
‫‪ ‬נהוג לקרוא לשיטות אלו ‪'setter‬ים ו‪'getter -‬ים‬
‫‪© Keren Kalif 30‬‬
‫האם תמיד התכונות יהיו ב‪?private -‬‬
‫‪ ‬ישנם מקרים בהם אין צורך בבדיקות תקינות עבור הערכי התכונות‬
‫‪ ‬למשל‪ ,‬עבור המחלקה ‪ Person‬המייצגת אדם‪ ,‬שתכונותיה הם שם ו‪-‬‬
‫ת‪.‬ז‪ ,.‬כאשר אין כרגע צורך בהגבלות תקינות‬
‫‪© Keren Kalif 31‬‬
‫האם תמיד התכונות יהיו ב‪?private -‬‬
‫(‪)2‬‬
‫‪ ‬אבל אם פתאום נחליט שמספר ת‪.‬ז‪ .‬חייב להיות ‪ 9‬ספרות‪ ,‬נצטרך‬
‫לעדכן את המחלקה‬
‫‪ ‬וה‪ main -‬כבר לא יתקמפל!‬
‫‪© Keren Kalif 32‬‬
‫תכונות תמיד יהיו ‪!private‬‬
‫‪ ‬אפילו אם בעת כתיבת המחלקה אין הגבלות תקינות על תכונה‪,‬‬
‫תמיד נשים אותה עם הרשאת ‪ private‬ונספק מתודות ‪ set‬ו‪get -‬‬
‫‪ 2 ‬סיבות מרכזיות לאופן כתיבה זה‪:‬‬
‫‪ .1‬שאם בעתיד תתווסף בדיקת תקינות‪ ,‬מי שמשתמש במחלקה לא‬
‫יצטרך לשנות את הקוד שלו‪ ,‬שכן כבר מראש הוא ישתמש במתודת‬
‫ה‪ ,set -‬וכל שינוי בתוך גוף המתודה יהיה שקוף מבחינתו‬
‫‪ .2‬אחידות‪ ,‬כך שהפניה לכל התכונות במחלקה תהייה באופן זהה‪,‬‬
‫באמצעות שיטות ‪ set‬או ‪get‬‬
‫‪© Keren Kalif 33‬‬
‫אתחול תכונות שהן ‪private‬‬
‫‪ ‬בהמשך נראה כיצד ניתן לתת ערכים לתכונות האובייקט עם‬
‫אתחולו‬
‫‪ ‬כרגע עם יצירת האובייקט כל ערכי שדותיו הם ‪0‬‬
‫‪ ‬נקפיד שתכונות האובייקט יהיו ‪!private‬‬
‫‪© Keren Kalif 34‬‬
‫תכנות מכוון עצמים בשפת ‪Java‬‬
‫‪ ‬שפת ‪ JAVA‬היא שפה מכוונת עצמים‪ ,‬ולכן כל דבר הוא אובייקט‪,‬‬
‫ובפרט התוכניות שלנו‬
‫‪ ‬התוכנית שלנו היא אובייקט מטיפוס ‪ Program‬ויש לו את השיטה‬
‫‪ ,main‬שהיא השיטה המופעלת עם הרצת התוכנית‪ .‬לאובייקט זה‬
‫אין תכונות‪:‬‬
‫‪© Keren Kalif 35‬‬
‫המחלקה ‪String‬‬
‫‪ ‬בשפת ‪ C‬כאשר רצינו להגדיר משתנה מטיפוס מחרוזת הגדרנו‬
‫מערך של תווים‪ ,‬הגבלנו את גודלו או שהקצנו דינאמית‬
‫‪ ‬בשפת ‪ JAVA‬יש את המחלקה ‪ String‬שמחזיקה מחרוזת‪ ,‬ואינה‬
‫מוגבלת בכמות התווים‬
‫‪ ‬המחלקה יודעת לנהל זאת בעצמה‬
‫‪ ‬המחלקה ‪ String‬היא מחלקה מיוחדת מאחר ולא ניתן לשנות את‬
‫ערכם של האובייקטים‬
‫‪ ‬כל שינוי האובייקט יוצר למעשה אובייקט חדש‬
‫‪© Keren Kalif 36‬‬
‫דוגמא‬
‫‪X1 = 53‬‬
‫‪X2 = 5‬‬
‫‪F‬‬
‫‪T‬‬
‫)‪str1 = “hello world” (id=24‬‬
‫)‪(id=22‬‬
‫”“ = ‪str2‬‬
‫‪“hello‬‬
‫)‪(id=23‬‬
‫)‪world” (id=24‬‬
‫‪T‬‬
‫‪F‬‬
‫‪T‬‬
‫‪T‬‬
‫ה‪ id -‬של משתנה מטיפוס ‪String‬‬
‫משתנה כאשר משנים את ערכו‬
‫השמה בין ‪ 2‬אובייקטים תפנה לאותו‬
‫מקום‪ ,‬כלומר יהיה להם ‪ id‬זהה‬
‫‪© Keren Kalif 37‬‬
‫בדיקת שוויון עבור אובייקטים באמצעות ==‬
‫בודקת את ההפניה‪ ,‬כלומר האם ה‪ id -‬זהה‪.‬‬
‫בדיקת שוויון באמצעות ‪ equals‬בודקת את התוכן‪.‬‬
‫המחלקה ‪StringBuffer‬‬
‫‪ ‬העבודה עם אובייקטים ממחלקת ‪ String‬שיש לשנותם יקרה‬
‫מבחינת ביצועים‪ ,‬מאחר ועדכון באובייקט גורר יצירת אובייקט‬
‫חדש‬
‫‪ ‬המחלקה ‪ StringBuffer‬משמשת גם היא לאיכסון מחרוזות‪ ,‬אך‬
‫היא יותר יעילה מבחינת ביצועים כאשר רוצים לעבוד עם מחרוזת‬
‫שמשנים את ערכה לעיתים תכופות‬
‫תזכורת‪ :‬שיטות המחלקה ‪ String‬ושימושן הוא ללימוד עצמי!‬
‫מומלץ גם להכיר את שיטות המחלקה ‪.StrinBUffer‬‬
‫‪© Keren Kalif 38‬‬
‫מה לא תקין בקוד הבא?‬
‫‪© Keren Kalif 39‬‬
‫ביחידה זו למדנו‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫מהו תכנות מכוון עצמים‬
‫מהו אובייקט‬
‫מהי מחלקה‬
‫תכונות ומתודות של מחלקות‬
‫יצירת אובייקט‬
‫תכנות מכוון עצמים בשפת ‪JAVA‬‬
‫‪ ‬הגדרות תכונות ושיטות‬
‫‪ ‬הרשאות גישה‬
‫‪ ‬המחלקה ‪String‬‬
‫‪© Keren Kalif 40‬‬
‫‪© Keren Kalif‬‬