Download int

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
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