1 / 42

מבוא למדעי המחשב

מבוא למדעי המחשב. הרצאה 18: פולימורפיזם ומחלקות אבסטרקטיות. class Student. public class Student { private static final int COURSE_PRICE = 1000; private String name ; private int id ; private int numOfCourses ; public Student( int id, String name) { this . name = name;

larose
Download Presentation

מבוא למדעי המחשב

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. מבוא למדעי המחשב הרצאה 18: פולימורפיזם ומחלקות אבסטרקטיות

  2. class Student publicclass Student { privatestaticfinalintCOURSE_PRICE = 1000; private String name; privateintid; privateintnumOfCourses; public Student(int id, String name) { this.name = name; this.id = id; numOfCourses= 0; } publicint computeTuition(){ returnnumOfCourses * COURSE_PRICE; } publicvoid setNumOfCourses(int c) { numOfCourses = c; } … } //class Student

  3. class Milgay publicclass Milgay extends Student { privateintmilga; public Milgay(int id, String name, int milga){ super(id, name); this.milga= milga; } publicint computeTuition(){ return Math.max(0, super.computeTuition() – milga); } … } //class Milgay

  4. הסטודנטים מוחים על שכר הלימוד • עקב מחאה של אגודת הסטודנטים החליטה האוניברסיטה להגיע עם הסטודנטים להסדר ולשנות את מנגנון התשלומים, כך שהתשלום המקסימאלי לסטודנט הוא 2500 ₪ • נוסיף למחלקה Student את הקבוע החדש MAX_PRICE, ואת השיטה computePayment() אשר תחשב את שכר הלימוד החדש

  5. class Student publicclass Student { privatestaticfinalintCOURSE_PRICE = 1000; privatestaticfinalintMAX_PRICE = 2500; private String name; privateintid; privateintnumOfCourses; public Student(int id, String name) { this.name = name; this.id = id; numOfCourses= 0; } publicint computeTuition (){ returnnumOfCourses * COURSE_PRICE; } publicvoid setNumOfCourses(int c) { numOfCourses = c; } publicint computePayment(){ returnMath.min(MAX_PRICE, computeTuition()); } } //class Student

  6. השפעת השינוי על סטודנט • עתה נריץ את הקוד הבא: Student s = new Student(11,"Dani"); s.setNumOfCourses(3); System.out.println(s. getName() + " should pay " + s.computePayment()); • הסטודנט יידרש לשלם 2500 ₪ במקום 3000 ₪, וכולם מרוצים.

  7. השפעת השינוי על מלגאי • עתה נריץ את הקוד הבא: Milgay m = new Milgay(12, "Moshe", 750); m.setNumOfCourses(3); System.out.println(m. getName() + “ should pay " + m.computePayment()); • כמה ישלם המלגאי?

  8. השפעת השינוי על מלגאי - פולימורפיזם • נבחן שתי אפשרויות: • אם computePayment יקרא ל- computeTuition של Student יחושב שכר לימוד של 3000 ₪ וכתוצאה מחישוב המינימום ישלם הסטודנט 2500 ₪. • אם computePayment יקרא ל- computeTuition של Milgay יחושב שכר לימוד של 2250 ₪ וכתוצאה מחישוב המינימום ישלם הסטודנט 2250 ₪. • אם האפשרות הראשונה נכונה, סביר שהמלגאי יכעס על יו"ר האגודה, שגרם לו לשלם 250 ₪ יותר • האפשרות הנכונה היא השנייה (ליו"ר שלום...)

  9. הסתרה של משתנים – עולם אחר • נוסיף את השדה הבא גם ל-Student וגם ל-Milgay: private int grade; • בנוסף, נוסיף למחלקה Student את הקוד: return grade;} } public int getGrade() • ולמחלקה Milgay את הקוד: this.grade = grade;}} public void setGrade(int grade) • עתה נריץ את השורות הבאות ב-main: m.setGrade(100); System.out.println(m.getName() + “ grade is " + m. getGrade()); מנגנון הפולימורפיזם לא פועל עבור משתנים (גם לא עבור ציבוריים...) 0 ???

  10. ומה לגבי שיטות private? • נוסיף ל-Student את השיטות: public void printClassName () {System.out.println(className());} private String className(){return “Student";} • ול-Milgay נוסיף את השיטה: private String className(){return “Milgay";} • ונריץ את הקוד הבא: m.printClassName(); מנגנון הפולימורפיזם לא פועל בשיטות פרטיות student

  11. ההרשאה protected אם כמתכנתי המחלקה Student אנו רוצים לאפשר למחלקות יורשות את הגישה למשתנה מחלקה כלשהו (numOfCourses ו- COURSE_PRICEבמקרה שלנו) אך עדיין איננו מעוניינים לחשוף משתנה זה למשתמשים חיצוניים, ניתן לתת למשתנה זה את מציין ההרשאה protected

  12. class Student publicclass Student { protected staticfinalintCOURSE_PRICE = 1000; private String name; privateintid; protected intnumOfCourses; public Student(int id, String name) { this.name = name; this.id = id; numOfCourses= 0; } publicint computeTuition(){ returnnumOfCourses * COURSE_PRICE; } publicvoid setNumOfCourses(int c) { numOfCourses = c; } … } //class Student

  13. class Milgay publicclass Milgay extends Student { privateintmilga; public Milgay(int id, String name, int milga){ super(id, name); this.milga= milga; } publicint computeTuitionFee(){ return(numOfCourses * COURSE_PRICE)-milga; } … } //class Milgay

  14. מחלקות אבסטרקטיות • רוצים לכתוב קוד המייצג מיכלים מסוגים שונים • צורות שונות: קופסא, חבית, קובייה • שיטות: • משותפות: הוספת נוזל, תכולה, האם מלא? • שונות: בנאים, חישוב קיבולת • האם ירושה מתאימה במקרה כזה? • האם יש אובייקט ממשי שנקרא מיכל?

  15. אולי ממשקים יעזרו? publicinterface Tank { publicdouble capacity(); publicdouble getContent(); publicvoid fill(double amount); publicboolean isFull(); }

  16. קופסא publicclass Box implements Tank { privatedoublecontents; privatedoublelength; privatedoublewidth; privatedoubleheight; //… (constructors) publicvoid fill(double amount){ contents = Math.min(contents + amount, capacity()); } publicdouble getContents(){ returncontents; } 16

  17. קופסא publicboolean isFull(){ return (contents == capacity()); } publicdouble capacity(){ returnlength*width*height; } } //class Box 17

  18. חבית publicclass Cylinder implements Tank{ privatedoublecontents; privatedoubleradius; privatedoubleheight; //… (constructors) publicvoid fill(double amount){ contents = Math.min(contents + amount, capacity()); } publicdouble getContents(){ returncontents; } 18

  19. חבית publicboolean isFull(){ return (contents == capacity()); } publicdouble capacity(){ returnheight * Math.PI * radius * radius; } }//class Cylinder 19

  20. חסרון: אותו הקוד מופיע במספר מחלקות 20

  21. הפתרון: מחלקות מופשטות publicabstractclass Tank{ privatedouble contents; publicabstractdouble capacity();

  22. הפתרון: מחלקות מופשטות publicabstractclass Tank{ privatedouble contents; public Tank(){ contents = 0; } publicabstractdouble capacity();

  23. publicvoid fill(double amount){ contents = Math.min(contents + amount, capacity()); } publicdouble getContents(){ return contents; } publicboolean isFull(){ return contents == capacity(); }  } // class Tank

  24. עכשיו ניתן להשתמש בהורשה publicclass Cylinder extends Tank{ privatedouble radius; privatedouble height; public Cylinder(double radius, double height){ super(); this.radius = radius; this.height = height; } publicdouble capacity(){ return height * Math.PI * radius * radius; } }

  25. קופסא class Box extends Tank{ privatedouble length; privatedouble width; privatedouble height; public Box(double length, double width, double height){ super(); this.length = length; this.width = width; this.height = height; } publicdouble capacity(){ return length * width * height; } }

  26. קובייה היא גם קופסא class Cube extends Box{ public Cube(double side){ super(side, side, side); } }

  27. ומה אם? publicclass Tank{ privatedouble contents; public Tank(){ contents = 0; } publicabstractdouble capacity(); Tank should be declared abstract; it does not define capacity() in Tank

  28. ומה אם? publicabstract class Tank{ privatedouble contents; public Tank(){ contents = 0; } publicdouble capacity(); missing method body, or declare abstract

  29. ומה אם? publicclass Cylinder extends Tank{ privatedouble radius; privatedouble height; public Cylinder(double radius, double height){ super(); this.radius = radius; this.height = height; } } Cylinder should be declared abstract; it does not define capacity() in Tank

  30. ומה קורה כשמנסים ליצור מופע? √ Tank t1 = new Cube(5); Tank t2 = new Tank(); X לא ניתן ליצור מופע של מחלקה אבסטרקטית!

  31. גם כאן אפשר protected • נניח כי אנו רוצים לאפשר למחלקות היורשות מ-Tank גישה ישירה לשדה contents: publicabstractclass Tank{ protecteddoublecontents; … } 31

  32. גם שיטות יכולות להיות protected • נניח כי אנו רוצים לדרוס ב-Tank את toString, כך שהמחרוזת המודפסת תכלול את סוג המיכל, קיבולתו ותוכנו: publicabstractclass Tank{ … public String toString(){ return concreteClassName() + ", capacity: " + capacity() + ", contents: " + contents; } protectedabstract String concreteClassName(); }// class Tank 32

  33. ועתה נתקן את המחלקות היורשות... publicclass Box extends Tank{ … protected String concreteTankClassName() { return"Box"; } }//class Box publicclass Cylinder extends Tank{ … protected String concreteTankClassName() { return"Cylinder"; } }//class Cylinder 33

  34. הערות מחלקות אבסטרקטיות וממשקים: במחלקה אבסטרקטית ניתן לממש חלק מהשיטות והבנאים, וכן להגדיר שדות. בממשק – לא. מחלקה יכולה לממש מספר ממשקים, אך לרשת מחלקה אחת בלבד (בפרט לרשת מחלקה אבסטרקטית אחת). אם מחלקה אבסטרקטית מכילה שיטות אבסטרקטיות בלבד, זה סימן שהיה נכון יותר לכתוב אותה כממשק. מחלקה אבסטרקטית יכולה "לממש" ממשק מבלי באמת לממש את כל השיטות בממשק. במקרה זה, ניתייחס לשיטות כאלו כשיטות אבסטרקטיות. מחלקה אבסטרקטית לא חייבת להכיל שיטות אבסטרקטיות.

  35. גן החיות שלנו חיה יונק ציפור כלב חתול

  36. ההגדרה של חיה publicabstractclass Animal { privateString name; publicString getName(){return name;} public Animal (String name){ this.name = name; } abstractpublicvoid eat(); abstractpublicvoid speak(); }

  37. ציפור publicclass Bird extends Animal { public Bird(String name){ super(name); } publicvoid eat(){ System.out.println(getName()+" eats Bissli"); } publicvoid speak(){ System.out.println("Twit twit"); } }

  38. יונק public abstractclass Mammal extends Animal { public Mammal(String name){ super(name); } publicvoid mammalSpecial(){ System.out.println("I’m a mammal!"); } } 38

  39. כלב publicclass Dog extends Mammal { public Dog(String name){ super(name); } publicvoid eat(){ System.out.println(getName()+" eats Dogli"); } publicvoid speak(){ System.out.println("Wouf!"); } }

  40. חתול publicclass Cat extends Mammal { public Cat(String name){ super(name); } publicvoid eat(){ System.out.println(getName()+" eats Catli"); } publicvoid speak(){ System.out.println("Meow"); } publicvoid purr(){ System.out.println("Purr"); } }

  41. הקמת הגן Scanner sc = new Scanner(System.in); Animal[] zoo = new Animal [10]; for (int i=0; i<zoo.length; i= i+1){ System.out.println("What animal do you want?"); String type = sc.next(); System.out.println(“How would you like to call it?"); if (type.equals("Dog")) zoo[i] = new Dog(sc.next()); elseif (type.equals("Cat")) zoo[i] = new Cat(sc.next()); else zoo[i] = new Bird(sc.next()); }

  42. אוכל וסיפור for (int i=0; i<zoo.length; i= i+1){ zoo[i].eat(); zoo[i].speak(); if (zoo[i] instanceof Mammal){ ((Mammal)zoo[i]).mammalSpecial(); if (zoo[i] instanceof Cat) ((Cat)zoo[i]).purr(); } }

More Related