Presentation is loading. Please wait.

Presentation is loading. Please wait.

Interface ממשקים 1. ראינו כי ניתן לשמור אובייקטים במערכים באותו אופן כמו משתנים רגילים. ננסה כעת לראות כיצד למיין מערך של אובייקטים מסוג מסוים. נשתמש.

Similar presentations


Presentation on theme: "Interface ממשקים 1. ראינו כי ניתן לשמור אובייקטים במערכים באותו אופן כמו משתנים רגילים. ננסה כעת לראות כיצד למיין מערך של אובייקטים מסוג מסוים. נשתמש."— Presentation transcript:

1 Interface ממשקים 1

2 ראינו כי ניתן לשמור אובייקטים במערכים באותו אופן כמו משתנים רגילים. ננסה כעת לראות כיצד למיין מערך של אובייקטים מסוג מסוים. נשתמש בשתי מחלקות חדשות, Student ו – Car 2

3 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

4 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

5 נתבונן במערך של מצביעים לאוביקטים מטיפוס Students: Students[] arr = new Student[10]; על מנת למיין אותו נבחר אחד מאלגוריתמי המיון שלמדנו, למשל InsertionSort 5

6 insertionSort public static void insertionSort(int[] array){ for (int i=1; i0 && (array[j-1] > value) ){ array[j] = array[j-1]; j = j-1; } array[j] = value; }//for }//insertionSort 6

7 מעבר למיון סטודנטים מהו הקושי העיקרי בשינוי הפונקציה כדי שתתאים למיון סטודנטים ? פעולת ההשוואה כמובן : array[j-1] > value הפעולה הראשונה שצריך לעשות היא להחליט על פעולת ההשוואה. למשל, השוואת מספר תעודת הזהות. עכשיו ניתן לכתוב : 7

8 מיון סטודנטים public static void insertionSort(Student[] array){ for (int i=1; i0 && (array[j-1].getId() > value.getId())){ array[j] = array[j-1]; j = j-1; } array[j] = value; } }//insertionSort(Student[] array) 8

9 עכשיו ניתן להפעיל : Students[] arr=new Student[10]; insertionSort(arr); ומה עם Car? Car[] arr=new Car[10]; insertionSort(arr);//???? 9

10 מיון מכוניות public static void insertionSort(Car[] array){ for (int i=1; i0 && (array[j-1].getModel() > value.getModel()) ){ array[j] = array[j-1]; j = j-1; } array[j] = value; } }//insertionSort(Car[] array) 10

11 אז מה פתרון אפשרי ? כמובן Object... public static void insertionSort(Object[] array){ for (int i=1; i0 && (array[j].???? > value. ????) ){ array[j] = array[j-1]; j = j-1; } array[j] = value; } }//insertionSort 11

12 ממשק - Interface אז כיצד נפתור זאת ? היינו רוצים להגיד שכל אובייקט שרוצה להיות בר - מיון יוכל להשתמש בפונקציית המיון הזאת. ראינו רעיון דומה עם equals ב ObjectSet... אם היתה לנו דרך להוסיף תכונת " בר - השוואה " לכל אובייקט שאנו רוצים למיין, היינו בדרך הנכונה. בדיוק למטרה זו, ב JAVA קיים המושג ממשק (interface) 12

13 ממשק הוא הגדרת התנהגות ללא מימוש 13

14 הממשק Comparable public interface Comparable { /** other an object to compare with this * Comparable object 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

15 הממשק Comparable בדוגמה שלנו, הגדרנו את התכונה תכונה " בר - השוואה ": public int compareTo(Object other); שימו לב כי השיטה compareTo היא חסרת מימוש. השיטה compareTo תחזיר מספר שלילי אם מקומו של האובייקט היוזם את הקריאה בסידור קודם למקום האובייקט המתקבל כפרמטר, מספר חיובי אם מקומו מאוחר, ואפס אם מקומם זהה. 15

16 ממשק הוא חוזה, וככל חוזה, יש לו שני צדדים : –כל מחלקה יכולה להתחייב לממש את החוזה, ובמקרה כזה היא מחוייבת לממש את כל השיטות המפורטות בחוזה. –ניתן להתייחס באופן אחיד למופעים של מחלקות המממשות חוזה מסוים מבלי לדעת מהן המחלקות הקונקרטיות שלהם. התייחסות כזו מאפשרת להפעיל על מופעים אלו את כל השיטות המופיעות בחוזה. 16

17 מי שרוצה להיות בעל התכונה " בר - השוואה " חייב לממש את כל השיטות המופיעות בממשק. אחרת, לא יעבור קומפילציה : public class Student implements Comparable{ … public int compareTo(Object other) { int otherId = ((Student)other).getId(); return id - otherId; } } // class Student 17

18 פתרון " מקצועי " יותר 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

19 אפשרות שנייה – סידור לקסיקוגרפי לפי שם. במקרה זה ניתן להשתמש בשיטה compareTo של String: 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); } } // class Student 19

20 ועבור המחלקה 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

21 בני השוואה עכשיו העצמים במחלקה Car וגם העצמים במחלקה Student הם בני - השוואה ( כלומר – שתי המחלקות " חתמו על החוזה " Comparable). ב JAVA ניתן להגדיר מצביעים אשר הטיפוס שלהם הוא ממשק, ובכך להתייחס לאובייקט המוצבע לפי התכונות המחייבות אותו אשר מופיעות בממשק. רעיון זה אינו מופרך – גם אנחנו מתייחסים לפעמים לתכונות ספציפיות של סטודנט או מרצה, ולפעמים לתכונות משותפות של שניהם כבני - אדם. לכן : Student s = new Student("shlomo",124); Comparable c = s; או למשל, Comparable c = new Student("shlomo",124); 21

22 שימו לב כי לא ניתו ליצור אובייקט מטיפוס ממשק : 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; func((Comparable) car3); 22

23 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

24 עכשיו נחזור למיון : 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

25 נקודות נוספות לדיון ומחשבה : הממשק שהגדרנו קיים בחבילה (package) java.lang, וחלק מהמחלקות המובנות ב -java מממשות אותו ( למשל String). אילו שיטות ניתן להפעיל על עצם ? לפי הטיפוס של המצביע, אלא אם כן עשינו casting. ממשק יכול להגדיר יותר משיטה אחת. מחלקה יכולה לממש יותר ממשק אחד : public class Car implements Comparable, Vehicle{…} ממשקים והנדסת תוכנה – אינטגרציה, תיקון באגים, חשיבה עתידית וגמישות. 25

26 ראינו מימוש של InsertionSort. כמובן שבאותו האופן קיימים MergeSort, BubbleSort וכו. נניח שנרצה למיין במספר אופנים שונים בתוכנית שלנו. היכן נמקם את השיטות הללו ? במחלקה אחת ? public class sortAlgorithms{ public static void InsertionSort(Comparable[] arr); public static void MergeSort(Comparable[] arr); … } 26

27 Sorter public interface Sorter{ public void sort(Comparable[] array); } עכשיו, כל מי שרוצה להוסיף שיטת מיון חדשה צריך פשוט לממש את הממשק Sorter: 27

28 class InsertionSorter implements Sorter{ public void sort(Comparable[] array){ … } }//class class MergeSorter implements Sorter{ public void sort(Comparable[] array){ … } }//class 28

29 דוגמה : Sorter s1= new InsertionSorter(); Student[] sArr=new Student[2]; sArr[0]=new Student( ,"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

30 Interface Replicable מוטיבציה xy getX() getY() xy getX() getY() xy getX() getY() מצב בלתי חוקי – שני עצמים זהים )לפי שיטת equals שלהם) בקבוצה. נובע מכך ששמרנו ב-add מצביע לאובייקט המקורי 30

31 public void add(Object o){ if ((o != null) && !contains(o) && (size

32 Interface Replicable מוטיבציה xy getX() getY() xy getX() getY() xy getX() getY() נרצה שבקבוצה יאוכסנו רק עותקים של העצמים. שאפשר יהיה להגיע אליהם רק דרך השיטות של הקבוצה. מה הבעיה? new Object לא ייצור את האובייקט שאני באמת רוצה – בזמן ריצה 32

33 public void add(Object o){ if ((o != null) && !contains(o) && (size

34 Replicable נגדיר ממשק Replicable, אשר כל מי שמממש אותו הוא " בר - הכפלה ". לממשק זה תהיה שיטה אחת בלבד אשר תחזיר עותק של האובייקט : public interface Replicable { /** a replicate of this object. */ public Object replicate(); } 34

35 נסתכל לדוגמה על המחלקה Point: public class Point implements Replicable { … public Object replicate(){ return new Point(this); } } 35

36 ReplicableObjectSet וכעת נגדיר מחלקה ReplicableObjectSet. מחלקה זו תהיה זהה לחלוטין למחלקה ObjectSet, אך תכלול שני הבדלים : –במקום לקבל בשיטה add פרמטר מסוג Object נקבל פרמטר מסוג Replicable. –הקבוצה תחזיק עותקים של האוביקטים שהכנסנו אליה, ולא את המקוריים. לגורמים חיצוניים לא תיהיה גישה ישירה אל אברי הקבוצה. 36

37 ReplicableObjectSet public class ReplicableObjectSet { … public void add(Replicable o){ if ((o != null) && !contains(o) && (size


Download ppt "Interface ממשקים 1. ראינו כי ניתן לשמור אובייקטים במערכים באותו אופן כמו משתנים רגילים. ננסה כעת לראות כיצד למיין מערך של אובייקטים מסוג מסוים. נשתמש."

Similar presentations


Ads by Google