חלק 1:
הורשה
ברצוננו לתאר בתוכנה מגוון של ביטויים חשבוניים. ביטוי חשבוני הוא ישות הניתנת לשערוך כגון מספר או פעולה
חשבונית המופעלת על שניים או שלושה ביטויים חשבוניים (כן – ההגדרה
רקורסיבית). כל ביטוי חשבוני יודע להדפיס
את עצמו.
עליך להגדיר את הישויות הבאות (מחלקות קונקרטיות, מחלקות מופשטות ומנשקים):
Expression – ישות המייצגת ביטוי כלשהו.
Literal – ישות המתארת מספר בודד (double).
BinaryOp – ישות המתארת פעולה בינארית (פעולה
על שני ביטויים).
TrenaryOp – ישות המתארת פעולה טרינארית (פעולה
על שלושה ביטויים).
Sum – ישות המתארת סכום.
Product - ישות המתארת מכפלה.
Exponent - ישות
המתארת חזקה.
CondExp – ישות המתארת פעולה על שלושה פרמטרים a, b, c שהיא
a ?
b : c . שערוך הביטוי מתבצע כך: אם
ערכו של a שונה מ 0.0 יוחזר
ערכו של b אחרת יוחזר ערכו של c.
בדקו את עצמכם ע"י קוד הלקוח הבא:
public class Client {
public static
void
main(String[] args) {
Expression l1 = new Literal(1.0);
Expression l2 = new Literal(2.0);
Expression l3 = new Literal(3.0);
Expression sum = new Sum(l1, l2);
Expression e1 = new Exponent(l3, sum);
Expression prod = new Product(l1, l2);
Expression exp = new Exponent(l2, l3);
Expression e2= new CondExp(sum, prod, exp);
System.out.println(e1 + " = " +
e1.eval());
System.out.println(e2
+ " = " + e2.eval());
}
}
פלט התוכנית הוא:
(3.0) ^ ((1.0) + (2.0)) = 27.0
((1.0) + (2.0)) ? ((1.0) * (2.0)) : ((2.0) ^ (3.0)) = 2.0
הערות:
public
double eval()
הציגו תרשים מחלקות המתאר את היחס בין הישויות שהגדרתם (מכונה גם עץ הורשה או היררכית מחלקות).
חלק שני: אוספים ממוינים
ניתן לכם מנשק SortedSet המייצג אוסף
של עצמים ממוינים ושונים אחד מן השני. מאחר והעצמים נשמרים בצורה ממוינת במימושים של מנשק זה, איטרטור על האוסף יחזיר אותם אחד-אחד בסדר עולה.
בנוסף ניתן לכם מימוש
פשוט של המנשק, מחלקה בשם SimpleSortedSet. מחלקה זו
תשמש אתכם אך ורק כדוגמה לצרכי תכנית הבדיקה המצורפת ושאר בדיקות שתרצו לעשות על
המימושים שלכם.
חשוב לשים לב כי כל ה-Sets
שנתעסק איתם הינם בלתי ניתנים לשינוי, ז"א שהעצמים
בתוכם נקבעים בעת היצירה. לא ניתן
להוסיף/להוריד עצמים לאחר
מכן מן האוספים. תכונה זו
תאפשר לכם לשמור תוצאות של חישובים ארוכים יחסית (ערך מקס',
ערך מינ', גודל) ולא לחשב אותם כל פעם מחדש.
שימו לב לאיטרטור SortedIterator, הרחבה ריקה של Iterator
שמסמלת כי האיטרטור מחזיר ערכים ממוינים.
א. CompositeSortedSet – בשלב זה תתכננו ותממשו מחלקה מופשטת. בשלבים הבאים נרחיב מחלקה זו.
size()
-->isEmpty()
-->getMinumum()
-->getMaximum()
ב. המחלקה MergedSortedSet שנבנית
באמצעות SortedSet A
ו-SortedSet B מכילה רק
עצמים בחיתוך של A ו-B
(ז"א עצמים
הנמצאים בשניהם). עבור מחלקה
זו עליכם לממש:
בנאי
-->contains()
-->iterator()
יצירת איטרטור צריכה
להראות כך:
/** * Returns an Iterator for the
elements of this set. */ public
SortedIterator iterator() { return new MergedSortedIterator(setA.iterator(),
setB.iterator()); } |
כמובן שתצטרכו לממש גם את MergedSortedIterator המרחיב את SortedIterator
ג. המחלקה DifferenceSortedSet שנבנית
באמצעות SortedSet A
ו-SortedSet B מכילה רק
עצמים שנמצאים ב-A אך לא נמצאים
ב-B. ממשו מחלקה זו (ואת האיטרטור המתאים לה) כמחלקה מרחיבה ל-CompositeSortedSet.
ד. המחלקה UnifiedSortedSet מכילה את כל העצמים מ-A ומ-B. ממשו אותה בדומה
לסעיפים הקודמים.