
GetEnumerator. בגלל שמדובר בעטיפה, מחזירים את items.GetEnumerator().הטקסט המלא של הדקות הראשונות בהרצאה «אוספים - Collections - חלק 3» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
בואו נפתח כאן פרויקט חדש נקרא לו arraylist-wrapper ובואו ניקח את אותה דוגמה שאנחנו ראינו בעבר נצרף מחלקה חדשה ואנחנו רוצים בעצם לעשות אוסף שראינו בעבר של מוצרים.
מה שאנחנו עשינו זה בעצם יצרנו מחלקה product ואז במיין יצרנו אובייקט arraylist בשביל להחזיק את כל המוצרים. מה שאנחנו הולכים לעשות עכשיו זה ראפר מעטפת ל-raylist ואנחנו הולכים לראות תוך כדי מה היתרונות בלעשות דבר כזה.
אז בואו נצרף מחלקה שמתארת אוסף של מוצרים, נקרא לה products חשוב שהיא תהיה ברבים לדוגמה מסתיימת ב-s. בואו נצרף את המחלקה הזאת וזאת תהיה ראפר לפרודקט.
לצורך כך בואו נוסיף את אותה מחלקה product שבנינו. בואו נלך ל-add existing Item, נעלה פה למעלה ונחפש את המחלקה הזאת שהייתה בפרודקטס קולקשן.
הנה המחלקה פרודקט, ברגע שאנחנו מצרפים קובץ אז הוא כמובן מועתק לעותק חדש ואנחנו יכולים להמשיך לעבוד איתו אצלנו. הנה הפרודקט וכעת יש לנו פרודקט בודד שמתאר לנו מוצר בודד ושימו לב שיש לו את כל היכולות בכדי להיות מנוהל על ידי אוסף.
הוא יורש את iCompatible ויש לו את Equals ו-GetHashCode ו-CompareTo ויש אפילו מחלקה ProductPriceComparer עם ה-Enum באיזה אורדר אתם רוצים לבצע את המיון וכולי וכולי. בסדר, את שני אלה אפשר להיפטר מהם בדוגמה הזאת.
טוב, אז זאת מחלקה שמתארת מוצר בודד, אחלה. אנחנו צריכים רק לשים לב שאנחנו רוצים שזה יהיה באותו ה-Namespace שלנו כדי שנוכל להשתמש איתה.
בצורה פשוטה, נחליף את הניימספייס וכעת מה שאנחנו רוצים לעשות זה ליצור מחלקת אוסף שיכולה לאסוף אך ורק אובייקטים מסוג פרודקט. עכשיו למחלקה כזאת יהיו כמה יתרונות. ראשית אנחנו לא רוצים שבאוסף שאנחנו בונים יהיה ניתן להכניס דברים אחרים.
בואו קודם כל נסגור את זאתי, את המחלקה הזאת נשים פה בצורה ורטיקלית, ניכנס למיין, אם היינו הולכים למיין ובונים arraylist myproducts היינו יכולים בתוך ה-arraylist להוסיף כל אובייקט שאנחנו רוצים, אפילו שהוא לא מוצר, היינו יכולים להוסיף את המחרוזת הלו.
אז יתרון ראשון במחלקה כזאת שאנחנו בונים זה שאנחנו מגדירים את הפונקציה add בתוך המחלקה שלנו שניתן לשלוח אליה רק אובייקטי product. כמובן גם נגזרות של פרודקט זה בסדר.
זה יתרון ראשון. יתרון שני, יכול להיות שאנחנו רוצים לבצע כל מיני פעולות שחוזרות על עצמן עם האוסף הזה.
זאת אומרת, יכול להיות שבהרבה מקומות אנחנו רוצים לבצע הצגות של כל המוצרים, שמירה לקובץ, טעינה מקובץ, תחפש לי את המוצר הזול ביותר, תחפש לי את המוצר היקר ביותר, תציג לי את הממוצע של כל המוצרים וכולי וכולי וכולי.
כל אחת מהפעילויות האלה אם אנחנו עובדים עם הריי ליסט כמו שהוא אנחנו צריכים לחזור ולבצע את הפעולה כאן בחוץ אנחנו צריכים לדוגמה לרוץ בפור איץ' על כל המוצרים בתוך המיי פרודקט ולבצע את ההצגה או את החיפוש של הממוצע של המוצרים וכולי וכולי שוב ושוב.
אם אנחנו בונים מחלקה ייעודית משלנו שיודעת לאסוף אך ורק מוצרים אז זה אומר שאנחנו יכולים בתוך המחלקה הזאת להגדיר את הפעילויות האלה וכך לא צריכים לחזור אליהם בכל פעם שאנחנו רוצים לבצע אותם.
זאת אומרת הפונקציה של הפעילות תהיה בתוך המחלקה וכך זה איזשהו שירות נוסף שהמחלקה מספקת למי שמשתמש בה ומי שמשתמש בה לא צריך לחזור שוב ושוב ולבצע את השירות הזה.
אוקיי, אז איך אנחנו עושים את זה? אז דבר ראשון יכול להיות שפתאום יקפוץ לכם רעיון שהוא יכול להיות רעיון דווקא מאוד מעניין ואתם יכולים לשאול את עצמכם למה שלא פשוט נירש את הריי ליסט ובעזרת חוק ההורשה נכתוב משהו שהוא יותר ספציפי מהריי ליסט.
הרי הרייליסט מסוגלת לאסוף כל דבר, זה מאוד כללי. אני רוצה לבנות מחלקה שמתארת מוצרים או אוסף של מוצרים, אם אני יורש את הרייליסט אני אולי יכול להיות יותר ספציפי.
והנקודה היא שאנחנו לא נעשה דבר כזה בגלל שחוק ההורשה אומר כזה דבר. אם אתם רוצים לבצע הורשה, אתם אוטומטית מקבלים את כל הפונקציות ואת כל המשתנים ואת כל מה שהיה במחלקת הבסיס ואתם לא יכולים לשנות שום דבר מהם.
ואם אנחנו מסתכלים על פולימורפיזם ועל היכולת שלנו לבצע דריסה של פונקציה, פולימורפיזם אומר שאנחנו יכולים לבצע דריסה ולכתוב תוכן חדש לפונקציה שהגיעה ממחלקת הבסיס אך ורק אם אנחנו שומרים על החתימה של הפונקציה.
ופה בעצם איבדנו את היכולת לשנות את החתימה מחתימה של פונקציה שמקבלת Object שזה הדבר שלא מתאים לנו לחתימה של פונקציה שמקבלת Product שזה הדבר שאנחנו רוצים לעשות. אז אם היינו רוצים לבצע דריסה public void לפונקציית add ולקבל Product לא היינו יכולים לעשות את זה עם Override מפני שפונקציית add ששייכת ל-array list, בעצם היא מקבלת אובג'קט ולא פרודקט.
שימו לב שאוטומטית קיבלנו פה איזושהי שגיאה שאומרת לנו no suitable method found to override. אנחנו לא יכולים לבצע דבר כזה על הפונקציה add.
אנחנו יכולים להוסיף פונקציה משלנו שנקראת add, אבל לא באמת ביצענו דריסה, וזה אומר שאם מתכנת בית ייצור אובייקט פרודקט, כעת פונקציית add בעצם תהיה לה שתי העמסות.
לא עשינו דריסה, עשינו משהו שנקרא העמסה. לא ביצענו override, ביצענו overload. ואז לא פתרנו את הבעיה, כי מתכנת בית שמשתמש באוסף שלנו כן יכול להוסיף לנו הלו.
ולכן לא ממש יעזור לנו לרשת את הרייליסט ולכתוב מחלקה יותר ספציפית, אלא מה שאנחנו צריכים לעשות זה לבנות בתוך המחלקה שלנו אובייקט מסוג הרייליסט.
פרייבט, הרייליסט, אייטמס בצורה כזאת. בואו ניפטר מזה. וכעת אנחנו בייסיקלי בונים ראפר על הרייליסט, וזה הרבה יותר נוח מאשר הדוגמה שראינו לבנות ראפר על מערך חד-ממדי.
מפני שאנחנו לא צריכים להתעסק עכשיו עם קפסיטי וקאונט וכולי, אנחנו צריכים רק לחשוף את הדברים שיש בתוך הרייליסט.
לדוגמה, בואו ניקח קונסטרקטור ריק, קונסטרקטור שמקבל קפסיטי, בקונסטרקטור הריק נגדיר את זה, את היצירה של האובייקט הריק, ובקונסטרקטור שקיבל capacity נגדיר הרייליסט עם ה-capacity שהביאו לנו.
נייצר property count ונחזיר את items.count. נייצר property capacity ונחזיר את items.capacity. תשימו לב שאנחנו ממש עוטפים את הרייליסט רק בכדי שנוכל להתעסק עם add כמו שצריך, עם remove כמו שצריך, ועם אופרטור סוגריים מרובעים כמו שצריך.
ב-add, כל מה שאנחנו צריכים לעשות זה לגשת ל-items.add ולהוסיף את המוצר. בואו נעשה פונקציית remove, היא תקבל product ותיגש ל-items ותסיר אותו. בואו נבצע פונקציית remove at שפשוט תקבל אינדקס, תיגש ל-items ל-remove at נשלח את האינדקס הזה לצורך הסרה.
ממש אנחנו כאילו חושפים כל דבר שקיים ב-ArrayList בכדי שאנחנו נהיה יותר ספציפיים. ובואו נבנה אופרטור סוגריים מרובעים, מה שנקרא אינדקסר, שמחזיר פרודקט, מקבל אינדקס, יש לו get ו-set.
אנחנו פה מחזירים את this, או ליתר דיוק items.index והפעולה ההפוכה זה להכניס לתוכו את ה-value. בואו נעשה פונקציית clear שקוראת ל-items clear וכעת סיימנו לחשוף את הדברים לפחות המרכזיים, אנחנו צריכים אולי גם sort וכולי, את הדברים המרכזיים שיש ב-araylist.
בואו נוסיף אפילו פונקציית sort בכדי שזה יהיה ממש ניתן למיון גם, items.sort והכל מסתדר לנו כמו שצריך. זה היתרון הראשון. היתרון הראשון זה שאנחנו עכשיו רוצים להוסיף מוצר myproducts.ad והנה אנחנו רואים שאנחנו לא יכולים לתת שום מחרובת ושום דבר שהוא לא פרודקט.
הדבר הזה הופך להיות שגיאת קומפילציה במקום שגיאת ריצה. תמיד שגיאות קומפילציה עדיפות על שגיאות ריצה כי אז המתכנת מתקן אותם מיידית והשגיאה לא מגיעה למצב שהיא מגיעה ללקוח בעוד חצי שנה פתאום מתרחשת לו.
אוקיי, אז מה שאני יכול לשלוח בעצם זה אך ורק אובייקטי פרודקט רגילים לגמרי. בואו ניתן פה איזה מוצר בצורה כזאת. יש לנו פה איזה שלושה מוצרים שהוספנו בעבר.
היתרון השני שיש לנו ושאנחנו יכולים עכשיו לייצר פונקציות ייעודיות עבור הקולקשן שלנו וזה אחד היתרונות הגדולים ביותר שלא מעריכים אותם מספיק כי הרבה פעמים קורה מצב שבתכנות אתם רוצים שיהיה לכם איזשהו קולקשן ואתם רואים לעצמכם מה עכשיו אני אלך ואני אפתח מחלקה מיוחדת