COMPARABLE NUMERIC REAL n class NUMERIC NUMERIC add
הורשה מרובה – עוד דוגמא (COMPARABLE) ( וגם בן השוואה NUMERIC) ( הוא גם מספרי REAL) מספר ממשי n class NUMERIC {. . . NUMERIC add (NUMERIC other); NUMERIC subtract (NUMERIC other); } class COMPARABLE {. . . boolean less. Than (COMPARABLE other); boolean less. Than. Equal (COMPARABLE other); } : ולכן הגיוני אולי שיירש משתיהן n class REAL extends NUMERIC , COMPARABLE { פילציה . . . ת קומ שגיא ! ר כזה } אין דב Java בשפת 1 תוכנה אוניברסיטת תל אביב 7
? מה הבעיה בירושה מרובה class Good. Driver implements Driver { boolean signal. Before. Turns() {return true; } } interface Driver {. . . } Class Opportunistic. Driver extends Good. Driver, Bad. Driver (not possible) class Bad. Driver implements Driver { boolean signal. Before. Turns() {return false; } } Java בשפת 1 תוכנה אוניברסיטת תל אביב 9
Abst. Stack Array. List. Stack Linked. List. Stack Abst. Stack Bounded. Stack Last. Modified. Stack Java בשפת 1 תוכנה אוניברסיטת תל אביב : סוגי מחסניות n Stacked. Stack : עוד סוגי מחסניות n Sum. Stack 10
Abst. Stack Array. List. Stack Bounded Array. List Stack Last. Modified Array. List Stack Linked. List. Stack Sum Array. List Stack Bounded Linked. List Stacked. Stack Bounded Stack Last. Modified Linked. List Stack Java בשפת 1 תוכנה אוניברסיטת תל אביב Last. Modified Stack Sum Stacked Stack Sum Linked. List Stack 12
public interface IStack<T> { public void push (T e); public void pop (); public T top (); } public class Simple. Stack<T> implements IStack<T> { private IStack. Impl<T> impl; // My. Array. List or My. Linked. List public Simple. Stack(IStack. Impl<T> impl) { this. impl = impl; } public void pop() { impl. remove(); } public void push(T e) { impl. insert(e); } public T top() { return impl. get(0); } } Java בשפת 1 תוכנה אוניברסיטת תל אביב 15
public class Last. Modified. Stack<T> extends Simple. Stack<T> { private Date last. Modified; public Last. Modified. Stack(IStack. Impl<T> impl) { super(impl); last. Modified = new Date(); } /** Push element and update */ public void push(T e) { last. Modified = new Date(); super. push(e); } /** Remove top element and update */ public void pop() { last. Modified = new Date(); super. pop(); } public Date get. Last. Modified() { return last. Modified; } } Java בשפת 1 תוכנה אוניברסיטת תל אביב אדישה למימוש Last. Modified. Stack ותעבוד בצורה זהה עם , של המחסנית כל מימוש שהוא 16
Array. List דוגמא למימוש המחסנית באמצעות n public class Array. List. Stack. Impl<E> implements IStack. Impl<E> { Array. List<E> rep = new Array. List<E>(); public E get(int index) { return rep. get(index); } public void insert(E e) { rep. add(e); public void remove() } { rep. remove(rep. size()-1); } } ? איך יראה לקוח טיפוסי שמעוניין ליצור מופע של מחסנית n Simple. Stack<Integer> stack = new Simple. Stack<Integer> (new Array. List. Stack. Impl<Integer>()); top המימוש של. יש פה באג מורכב לא קונסיסטנטי Simple. Stack ב remove עם המימוש של ? מה החסרונות של מבנה זה ? איך ניתן לפתור אותם Java בשפת 1 תוכנה אוניברסיטת תל אביב • • 18
מנשק מחסנית interface Stack { public Object top (); public void push(Object t); public void pop(); public boolean empty(); public boolean full(); } Java בשפת 1 תוכנה אוניברסיטת תל אביב 21
מימוש מחסנית פשוט public class Fixed. Capacity. Stack implements Stack{ private Object [] content; private int capacity; private int top. Index; public Fixed. Capacity. Stack(int capacity){ content = new Object[capacity]; this. capacity = capacity; top. Index = -1; } public Object top () { return content[top. Index]; } Java בשפת 1 תוכנה אוניברסיטת תל אביב 22
מימוש מחסנית פשוט public void push(Object t) { content[++top. Index] = t; } public void pop() { top. Index--; } public boolean empty() { return (top. Index < 0); } public boolean full() { return (top. Index >= capacity - 1) ; } } Java בשפת 1 תוכנה אוניברסיטת תל אביב 23
? איך נשתמש במחסנית : נניח שרוצים מחסנית של מחרוזות n Stack s = new Fixed. Capacity. Stack(5); s. push("hello"); String t 1 = s. top(); // compilation error String t 2 = (String) s. top(); //ok באחריות המתכנתת לוודא שכל האברים המוכנסים למחסנית הם מאותו n. ייכשל Casting אחרת ה , ( טיפוס )כאן מחרוזות Stack s = new Fixed. Capacity. Stack(5); s. push("hello"); s. push(new Integer(4)); s. push(new Polar. Point(3, 2)); String t 2 = (String) s. top(); //compilation ok. Runtime Error ! Java בשפת 1 תוכנה אוניברסיטת תל אביב 24
בטיחות טיפוסים Stack <String> ss = new FCStack <String> (5); ss. push("The letter A"); ss. push(new Integer(3)); String t = ss. top(); // same as: (String)ss. top(); מכיוון שרק מחרוזות יכולות להיות מוכלות במחסנית אין עוד צורך בהמרה n Stack <Rectangle> sr = new FCStack <Rectangle>(5); Rectangle rr = new Rectangle(. . . ) Rectangle rc = new Colored. Rectangle(. . . ) Colored. Rectangle cc = new Colored. Rectangle(. . . ) sr. push(rr); sr. push(rc); sr. push(cc); Java בשפת 1 תוכנה אוניברסיטת תל אביב 28
is-a הכללה ויחס ? Stack <String> ts = new FCStack <String> (5); Stack <Object> to = new FCStack <Object> (5); to = ts; ts. push("The letter A"); ts. push(new Integer(3)); to. push(new Integer(3)); FCStack<Object> אינו סוג של FCStack<String> : מסקנה n. זה לא אינטואיטיבי אבל נכון n Java בשפת 1 תוכנה אוניברסיטת תל אביב 29
ג'וקרים (? - נשתמש בג'וקר )סימן שאלה n public static void print. List(List<? > list) { for(int i=0, n=list. size(); i < n; i++) { if (i % 2 == 0) { Object obj = list. get(i); System. out. println(obj); } } } Java בשפת 1 תוכנה אוניברסיטת תל אביב 38
ג'וקרים : כמו בשרות , כדי שנוכל לבצע פעולות על אברי הרשימה יש לספק חסם עליון n public static double sum. Perimiters(List<? extends IShape> list) { double total = 0. 0; for(IShape n : list) total += n. perimeter(); return total; } , IShape הוא טיפוס המרחיב את list הטיפוס הגנרי של : משמעות ההגדרה n . עצמו כמובן IShape כולל . זהו תחביר מיוחד להרחבות. גם עבור מנשקים extends שימו לב לשימוש ב n List<IShape> shapes =. . . : שימוש בשירות n List<Circle> circles =. . . List<Triangle> triangles =. . . double shapes. Perimeter. Sum = sum. Perimiters(shapes); double circles. Perimeter. Sum = sum. Perimiters(circles); double triangles. Perimeter. Sum =sum. Perimiters(triangles); Java בשפת 1 תוכנה אוניברסיטת תל אביב 39
ג'וקרים : יש גם חסמים תחתונים n public static boolean add. Item(List<? super Colored. Rectangle> lst, Colored. Rectangle item) { return lst. add(item); } או טיפוס Colored. Rectangle הוא list הטיפוס הגנרי של הרשימה : המשמעות n. מרחיב Colored. Rectangle שאותו List<Colored. Rectangle> c. Rectangles=. . . ; List<Rectangle> rectangles=. . . ; List<Object> objects=. . . ; Colored. Rectangle c. Rect=. . . ; add. Item(c. Rectangles, c. Rect); add. Item(rectangles, c. Rect); add. Item(objects, c. Rect); Java בשפת 1 תוכנה אוניברסיטת תל אביב : שימוש בשירות n 40
שירותים מוכללים ולא רק , ניתן להגדיר טיפוס גנרי עבור שירות בודד n. למחלקה class Test{ public static void main(String[] args){ List<Integer> int. Lst = Arrays. as. List(1, 2, 3); List<String> str. Lst = Arrays. as. List("a", "b", "c"); int first. Int = get. First. Item(int. Lst); מכיל get. First. Item השירות String first. Str = get. First. Item(str. Lst); . <T> פרמטר גנרי } ערכו של הפרמטר הגנרי יקבע , למשל. בזמן הקריאה לשירות List<String> כאשר נשלח /* יקבע ל T ערכו של , כפרמטר * @pre list. size() > 0. String */ public static <T> T get. First. Item(List<T> list){ return list. get(0); } } Java בשפת 1 תוכנה אוניברסיטת תל אביב 41
. . . ובהקשר של מחלקות פנימיות public class My. Type<E>{ class Inner{} static class Nested{} public static void main(String[] args) { My. Type mt; //warning: My. Type is a raw type My. Type. Inner inn; //warning: My. Type. Inner is a raw type My. Type. Nested nest; //no warning, not a parametrized type My. Type<Object> mt 1; //no warning My. Type<? > mt 2; //no warning, ? is OK for a type } } Java בשפת 1 תוכנה אוניברסיטת תל אביב 42
? למה טוב שהקומפיילר שומר List names = new Array. List(); //warning: raw type names. add("Kyle"); names. add("Eric"); names. add(Boolean. FALSE); for (Object o : names){ גילוי השגיאה String s = (String)o; System. out. println(s. to. Upper. Case()); בזמן קומפילציה ! ולא בזמן ריצה } //throws Class. Cast. Exception // java. lang. Boolean cannot be cast to java. lang. String List<String> names = new Array. List<>(); names. add("Kyle"); names. add("Eric"); names. add(Boolean. FALSE); //compilation error! Java בשפת 1 תוכנה אוניברסיטת תל אביב 43
<Object> שונה מ Raw public static void main(String[] args){ List<String> str. Lst = new Array. List<>(); append. New. Object(str. Lst); //compilation error! } public static void append. New. Object(List<Object> lst){ lst. add(new Object()); } היתה append. New. Object מה היה קורה אם הפונקציה ? נא List מקבלת Java בשפת 1 תוכנה אוניברסיטת תל אביב 44
(wildcard) <? > שונה מ Raw public static void main(String[] args){ List<String> str. Lst = new Array. List<>(); append. New. Object(str. Lst); //this is fine } public static void append. New. Object(List<? > lst){ lst. add(new Object()); //compilation error! } כמובן שזה לא הגיוני שיהיה ניתן לרשימה Object להוסיף עצם מטיפוס צריך למנוע את זה , לכן , של מחרוזות . כבר בשלב הקומפילציה Java בשפת 1 תוכנה אוניברסיטת תל אביב 45
>? < כמחלקת בסיס public static void print. Collection(Collection<? > c){ for (Object o: c){ System. out. println(o); } } . כל אוסף print. Collection ניתן לשלוח לפונקציה n c ניתן לגשת לאלמנטים מתוך print. Collection בתוך n. Object ולשייך להם את הטיפוס הסטטי Collection<? > c = new Array. List<>(); c. add(new Object()); // Compile time error Java בשפת 1 תוכנה אוניברסיטת תל אביב 46
דוגמא public class Math. Wizard {. . . /** returns the square root of num * @pre epsilon >= 10 ^(-6) * @post abs($ret*$ret – num) <= epsilon */ double sqrt(int num, double epsilon); . . . } Java בשפת 1 תוכנה אוניברסיטת תל אביב 57
דוגמא public class Accurate. Math. Wizard extends Math. Wizard {. . . /** returns the square root of num * @pre epsilon >= 10^(-20) * @post abs($ret*$ret – num) <= epsilon/2 */ double sqrt(int num, double epsilon); . . . } ( בדוגמא תנאי הקדם חלש יותר )מרשה יותר ערכי אפסילון n ( ותנאי הבתר יותר חזק )מבטיח דיוק רב יותר Java בשפת 1 תוכנה אוניברסיטת תל אביב 58
is-a חס מתק י י ם י לא מלבן לא יורש מריבוע public class Square { protected double length; public class Rectangle extends Square { protected double width; public double get. Length(){ return length; } public double get. Width(){ return width; } public double get. Width(){ return length; } public double area(){ return length*length; }. . . } public double area(){ return length*width; }. . . } Rectangle is NOT a Square – ברור כי העיצוב לקוי n get. Length()==get. Width() צריך להכיל את Square למשל המשתמר של n לא שומר על כך Rectangle וברור כי n Java בשפת 1 תוכנה אוניברסיטת תל אביב 71
- Slides: 72