Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Interface ממשקים 1 • ראינו כי ניתן לשמור אובייקטים במערכים באותו אופן כמו משתנים רגילים. • ננסה כעת לראות כיצד למיין מערך של אובייקטים מסוג מסוים. • נשתמש בשתי מחלקות חדשות Student ,ו – Car 2 Student public class Student { // Sate: private String name; private int id; // Constructors: public Student(int id, String name) { this.name = name; this.id = id; } // Behavior: … } // class Student 3 Car public class Car { // Sate: private String company; private int model; // Constructors: public Car(int model, String company) { this.company = company; this.model = model; } // Behavior: … } // class Car 4 נתבונן במערך של מצביעים לאוביקטים מטיפוס :Students ;]Students[] arr = new Student[10 על מנת למיין אותו נבחר אחד מאלגוריתמי המיון שלמדנו ,למשל InsertionSort 5 insertionSort public static void insertionSort(int[] array){ for (int i=1; i<array.length; i=i+1){ int value = array[i]; int j = i; while(j>0 && (array[j-1] > value) ){ array[j] = array[j-1]; j = j-1; } array[j] = value; }//for }//insertionSort 6 מעבר למיון סטודנטים • מהו הקושי העיקרי בשינוי הפונקציה כדי שתתאים למיון סטודנטים? פעולת ההשוואה כמובןarray[j-1] > value : הפעולה הראשונה שצריך לעשות היא להחליט על פעולת ההשוואה .למשל ,השוואת מספר תעודת הזהות. עכשיו ניתן לכתוב: 7 מיון סטודנטים public static void insertionSort(Student[] array){ for (int i=1; i<array.length; i = i+1){ Student value = array[i]; int j = i; while(j>0 && (array[j-1].getId() > value.getId())){ array[j] = array[j-1]; j = j-1; } array[j] = value; } }//insertionSort(Student[] array) 8 :• עכשיו ניתן להפעיל Students[] arr=new Student[10]; insertionSort(arr); ?Car ומה עם Car[] arr=new Car[10]; insertionSort(arr);//???? 9 מיון מכוניות public static void insertionSort(Car[] array){ for (int i=1; i<array.length; i = i+1){ Car value = array[i]; int j = i; while(j>0 && (array[j-1].getModel() > value.getModel()) ){ array[j] = array[j-1]; j = j-1; } array[j] = value; } }//insertionSort(Car[] array) 10 ...Object אז מה פתרון אפשרי? כמובן public static void insertionSort(Object[] array){ for (int i=1; i<array.length; i=i+1){ Object value = array[i]; int j = i; while(j>0 && (array[j].???? > value. ????) ){ array[j] = array[j-1]; j = j-1; } array[j] = value; } }//insertionSort 11 ממשק Interface - • אז כיצד נפתור זאת? היינו רוצים להגיד שכל אובייקט שרוצה להיות בר-מיון יוכל להשתמש בפונקציית המיון הזאת .ראינו רעיון דומה עם equalsב ...ObjectSet • אם היתה לנו דרך להוסיף תכונת "בר-השוואה" לכל אובייקט שאנו רוצים למיין ,היינו בדרך הנכונה. • בדיוק למטרה זו ,ב JAVAקיים המושג ממשק ()interface 12 ממשק הוא הגדרת התנהגות ללא מימוש 13 Comparable הממשק public interface Comparable { /** * @param other an object to compare with this * Comparable object * @return a negative value, 0, or a positive value, * if this object has a lower, an identical, or a * higher rank in the order, respectively. */ public int compareTo(Object other); } 14 הממשק Comparable • בדוגמה שלנו ,הגדרנו את התכונה תכונה "בר- השוואה": ;)public int compareTo(Object other • שימו לב כי השיטה compareToהיא חסרת מימוש. • השיטה compareToתחזיר מספר שלילי אם מקומו של האובייקט היוזם את הקריאה בסידור קודם למקום האובייקט המתקבל כפרמטר ,מספר חיובי אם מקומו מאוחר ,ואפס אם מקומם זהה. 15 • ממשק הוא חוזה ,וככל חוזה ,יש לו שני צדדים: – כל מחלקה יכולה להתחייב לממש את החוזה ,ובמקרה כזה היא מחוייבת לממש את כל השיטות המפורטות בחוזה. – ניתן להתייחס באופן אחיד למופעים של מחלקות המממשות חוזה מסוים מבלי לדעת מהן המחלקות הקונקרטיות שלהם .התייחסות כזו מאפשרת להפעיל על מופעים אלו את כל השיטות המופיעות בחוזה. 16 השוואה" חייב לממש את כל-מי שרוצה להיות בעל התכונה "בר : לא יעבור קומפילציה, אחרת.השיטות המופיעות בממשק public class Student implements Comparable{ … public int compareTo(Object other) { int otherId = ((Student)other).getId(); return id - otherId; } } // class Student 17 פתרון "מקצועי" יותר public class Student implements Comparable{ … public int compareTo(Object other) { if (!(other instanceof Student)){ throw new RuntimeException( "CompareTo got a non-Student parameter."); } int otherId = ((Student)other).getId(); return id - otherId; } } // class Student 18 במקרה זה.אפשרות שנייה – סידור לקסיקוגרפי לפי שם :String שלcompareTo ניתן להשתמש בשיטה public class Student implements Comparable{ … public int compareTo(Object other) { if (!(other instanceof Student)){ throw new RuntimeException( "CompareTo got a non-Student parameter."); } String otherName = ((Student)other).getName(); return name.compareTo(otherName); } } 19 // class Student :Car ועבור המחלקה public class Car implements Comparable{ … public int compareTo(Object other){ if (!(other instanceof Car)){ throw new RuntimeException("CompareTo got a non-Car parameter."); } int otherModel = ((Car)other).getModel(); return model - otherModel; } } // class Car 20 בני השוואה • עכשיו העצמים במחלקה Carוגם העצמים במחלקה Studentהם בני-השוואה (כלומר – שתי המחלקות "חתמו על החוזה" .)Comparable • ב JAVAניתן להגדיר מצביעים אשר הטיפוס שלהם הוא ממשק, ובכך להתייחס לאובייקט המוצבע לפי התכונות המחייבות אותו אשר מופיעות בממשק .רעיון זה אינו מופרך – גם אנחנו מתייחסים לפעמים לתכונות ספציפיות של סטודנט או מרצה ,ולפעמים לתכונות משותפות של שניהם כבני-אדם. • לכן: ;)Student s = new Student("shlomo",124 ;Comparable c = s או למשל, ;)Comparable c = new Student("shlomo",124 21 :שימו לב כי לא ניתו ליצור אובייקט מטיפוס ממשק Comparable c = new Comparable(); . ולא מחלקה, היא בסה"כ תכונהComparable – הסיבה היא פשוטה public static void func(Comparable c){…} Car car1 = new Car(2004, "Toyota"); Comparable car2 = new Car(1990, "Mercedes"); Point p = new Point(1,1); Object car3 = new Car(1982, "Lada"); func(car2); func(car1); func(p); func(car3); func((Comparable) car3); func((Comparable) p); Car3 = p; 22 func((Comparable) car3); • • Sorting both Students and Cars public static void main(String[] args) { Student[] myStudents = new Student[2]; myStudents[0] = new Student(2, "Vika"); myStudents[1] = new Student(1, "Dan"); System.out.println(arr2String(myStudents)); insertionSort(myStudents); System.out.println(arr2String(myStudents)); Car c1 = new Car(2004, "Toyota"); Car c2 = new Car(1990, "Mercedes"); Car[] myCars = {c1,c2}; System.out.println(arr2String(myCars)); insertionSort(myCars); System.out.println(arr2String(myCars)); } 23 :עכשיו נחזור למיון public static void insertionSort(Comparable[] array){ Comparable value; for (int i=1; i < array.length; i = i+1){ value = array[i]; int j = i; while(j>0 && array[j-1].compareTo(value) > 0){ array[j] = array[j-1]; j = j-1; } array[j] = value; } }//insertionSort(Comparable[] array) 24 נקודות נוספות לדיון ומחשבה: • • • • • הממשק שהגדרנו קיים בחבילה (,java.lang )package וחלק מהמחלקות המובנות ב java-מממשות אותו (למשל .)String אילו שיטות ניתן להפעיל על עצם? לפי הטיפוס של המצביע ,אלא אם כן עשינו .casting ממשק יכול להגדיר יותר משיטה אחת. מחלקה יכולה לממש יותר ממשק אחד: public class Car implements }…{Comparable, Vehicle ממשקים והנדסת תוכנה – אינטגרציה ,תיקון באגים, חשיבה עתידית וגמישות. 25 כמובן שבאותו.InsertionSort • ראינו מימוש של . וכוMergeSort, BubbleSort האופן קיימים • נניח שנרצה למיין במספר אופנים שונים בתוכנית .שלנו ?• היכן נמקם את השיטות הללו? במחלקה אחת public class sortAlgorithms{ public static void InsertionSort(Comparable[] arr); public static void MergeSort(Comparable[] arr); … } 26 Sorter public interface Sorter{ public void sort(Comparable[] array); } כל מי שרוצה להוסיף שיטת מיון חדשה צריך,עכשיו :Sorter פשוט לממש את הממשק 27 class InsertionSorter implements Sorter{ public void sort(Comparable[] array){ … } }//class class MergeSorter implements Sorter{ public void sort(Comparable[] array){ … } }//class 28 :דוגמה Sorter s1= new InsertionSorter(); Student[] sArr=new Student[2]; sArr[0]=new Student(2352452,"david"); sArr[1]=new Student(111252,"Anat"); s1.sort(sArr); Sorter s2= new MergeSorter(); Car[] cArr=new Car[2]; cArr[0]=new Car(2004,"toyota"); cArr[1]=new Car(1943,"Ford"); s2.sort(cArr); 29 Interface Replicable מוטיבציה y y )(getX )(getY x )(getX )(getY x y x )(getX )(getY מצב בלתי חוקי – שני עצמים זהים )לפי שיטת equalsשלהם) בקבוצה. נובע מכך ששמרנו בadd- מצביע לאובייקט המקורי 30 public void add(Object o){ if ((o != null) && !contains(o) && (size<elements.length)){ elements[size] = o; size = size + 1; } }//add 31 Interface Replicable מוטיבציה y y )(getX )(getY x )(getX )(getY x y x )(getX )(getY נרצה שבקבוצה יאוכסנו רק עותקים של העצמים .שאפשר יהיה להגיע אליהם רק דרך השיטות של הקבוצה. מה הבעיה? new Objectלא ייצור את האובייקט שאני באמת רוצה – בזמן ריצה 32 public void add(Object o){ if ((o != null) && !contains(o) && (size<elements.length)){ elements[size] = new Object(o); size = size + 1; } }//add 33 Replicable - אשר כל מי שמממש אותו הוא "בר,Replicable • נגדיר ממשק לממשק זה תהיה שיטה אחת בלבד אשר תחזיר עותק."הכפלה :של האובייקט public interface Replicable { /** * @return a replicate of this object. */ public Object replicate(); } 34 :Point נסתכל לדוגמה על המחלקה public class Point implements Replicable { … public Object replicate(){ return new Point(this); } } 35 ReplicableObjectSet • וכעת נגדיר מחלקה .ReplicableObjectSet מחלקה זו תהיה זהה לחלוטין למחלקה ,ObjectSetאך תכלול שני הבדלים: – במקום לקבל בשיטה addפרמטר מסוג Objectנקבל פרמטר מסוג .Replicable – הקבוצה תחזיק עותקים של האוביקטים שהכנסנו אליה ,ולא את המקוריים .לגורמים חיצוניים לא תיהיה גישה ישירה אל אברי הקבוצה. 36 ReplicableObjectSet public class ReplicableObjectSet { … public void add(Replicable o){ if ((o != null) && !contains(o) && (size<elements.length)){ elements[size] = o.replicate(); size = size + 1; } }//add 37