Everything the light touches, Simba, will be yours

Slides:



Advertisements
Similar presentations
CE203 - Application Programming Autumn 2013CE203 Part 31 Part 3.
Advertisements

Inheritance // A simple class hierarchy. // A class for two-dimensional objects. class TwoDShape { double width; double height; void showDim() { System.out.println("Width.
Problem Solving 5 Using Java API for Searching and Sorting Applications ICS-201 Introduction to Computing II Semester 071.
METHOD OVERRIDING Sub class can override the methods defined by the super class. Overridden Methods in the sub classes should have same name, same signature.
METHOD OVERRIDING 1.Sub class can override the methods defined by the super class. 2.Overridden Methods in the sub classes should have same name, same.
1 Inheritance Chapter 9. 2 Module Outcomes To develop a subclass from a superclass through inheritance To invoke the superclass ’ s constructors and methods.
1 SSD3 - Unit 2 Java toString & Equals Presentation Class Website:
1 CS 171: Introduction to Computer Science II Review: OO, Inheritance, and Libraries Ymir Vigfusson.
1. 2 Introduction to Inheritance  Access Modifiers  Methods in Subclasses  Method Overriding  Converting Class Types  Why up-cast?  Why down-cast?
Liang, Introduction to Java Programming, Eighth Edition, (c) 2011 Pearson Education, Inc. All rights reserved Inheritance and Polymorphism.
1. 2 Introduction to Methods  Type of Variables  Static variables  Static & Instance Methods  The toString  equals methods  Memory Model  Parameter.
1 More on Inheritance Overview l Object: The father of all classes l Casting and Classes l Object Cloning l Importance of Cloning.
1 Inheritance Overview l Inheritance ensures Reusability l Example of Inheritance l What is actually Inherited? l Overloading Vs. Overriding l Object:
Object-Orientated Design and Programming Unit 8: Inheritance and Polymorphism Jin Sa.
1 Inheritance and Polymorphism. 2 Motivations Suppose you will define classes to model circles, rectangles, and triangles. These classes have many common.
Unit 011 Inheritance Recall What Inheritance is About The extends Keyword The Object Class Overriding versus Overloading What is Actually Inherited? Single.
Inheritance Part II. Lecture Objectives To learn about inheritance To understand how to inherit and override superclass methods To be able to invoke superclass.
1 Introduction to Inheritance Overview l Inheritance ensures Reusability l Example of Inheritance l What is actually Inherited? l Overloading Vs. Overriding.
Inheritance Motivation –Code reuse –Conceptual modeling.
1 Inheritance and Polymorphism Chapter 9. 2 Polymorphism, Dynamic Binding and Generic Programming public class Test { public static void main(String[]
Liang, Introduction to Java Programming, Tenth Edition, (c) 2013 Pearson Education, Inc. All rights reserved. 1 Chapter 11 Inheritance and Polymorphism.
Intro to OOP with Java, C. Thomas Wu
1 Object-Oriented Software Engineering CS Interfaces Interfaces are contracts Contracts between software groups Defines how software interacts with.
Programming With Java ICS201 University Of Ha’il1 Chapter 8 Polymorphism and Abstract Classes.
Inheritance. Inheritance Early programmers often wrote code very similar to existing code Example: A human resources system might handle different types.
Java Quiz Bowl A fun review of the Java you should know from CMPT 201 If you don’t know the answers - this week is for you to study up!
Liang, Introduction to Java Programming, Ninth Edition, (c) 2013 Pearson Education, Inc. All rights reserved. 1 Chapter 11 Inheritance and Polymorphism.
Inheritance and Polymorphism Daniel Liang, Introduction to Java Programming.
 Definition: The ability to derive child classes (sub- classes) from parent classes (super-classes)  Characteristics:  Methods and instance variables.
CSE 143 Lecture 23 Polymorphism; the Object class read slides created by Marty Stepp and Ethan Apter
Liang, Introduction to Java Programming, Seventh Edition, (c) 2009 Pearson Education, Inc. All rights reserved
Chapter 5 Objects and Classes Inheritance. Solution Assignments 3 & 4 Review in class…..
Liang, Introduction to Java Programming, Sixth Edition, (c) 2007 Pearson Education, Inc. All rights reserved Chapter 9 Inheritance and.
Liang, Introduction to Java Programming, Seventh Edition, (c) 2009 Pearson Education, Inc. All rights reserved Chapter 10 Inheritance and.
CSE 143 Lecture 20 Abstract classes. 2 Circle public class Circle { private double radius; public Circle(double radius) { this.radius = radius; } public.
Recitation 8 User Defined Classes Part 2. Class vs. Instance methods Compare the Math and String class methods that we have used: – Math.pow(2,3); – str.charAt(4);
Lecture 4: Extending Classes. Concept Inheritance: you can create new classes that are built on existing classes. Through the way of inheritance, you.
Application development with Java Lecture 21. Inheritance Subclasses Overriding Object class.
Interfaces and Inner Classes
Announcements Final Exam: TBD. Static Variables and Methods static means “in class” methods and variables static variable: one per class (not one per.
CSI 3125, Preliminaries, page 1 Inheritance. CSI 3125, Preliminaries, page 2 Inheritance Using inheritance, can create a general class that defines traits.
1 Object-Oriented Programming Inheritance. 2 Superclasses and Subclasses Superclasses and Subclasses  Superclasses and subclasses Object of one class.
Inheritance ndex.html ndex.htmland “Java.
Liang, Introduction to Java Programming, Seventh Edition, (c) 2009 Pearson Education, Inc. All rights reserved Chapter 10 Inheritance and Polymorphism.
COMP Inheritance and Polymorphism Yi Hong June 09, 2015.
Programming in Java Transitioning from Alice. Becomes not myFirstMethod but …. public static void main (String[] arg) { // code for testing classes goes.
Catie Welsh April 18,  Program 4 due Wed, April 27 th by 11:59pm  Final exam, comprehensive ◦ Friday, May 6th, 12pm  No class Friday - Holiday.
Chapter 11 Inheritance and Polymorphism
Chapter 11 Inheritance and Polymorphism
Lecture 17: Polymorphism (Part II)
Chapter 5 Hierarchies IS-A associations superclasses subclasses
Web Design & Development Lecture 5
CS 302 Week 14 Jim Williams, PhD.
CS 302 Week 11 Jim Williams, PhD.
Variables as Remote Control
Overloading and Constructors
Chapter 9 Inheritance and Polymorphism
More inheritance, Abstract Classes and Interfaces
Extending Classes.
Advanced Programming Behnam Hatami Fall 2017.
Inheritance.
Building Java Programs
Assignment 7 User Defined Classes Part 2
Sampath Kumar S Assistant Professor, SECE
Lecture 18: Polymorphism (Part II)
Web Design & Development Lecture 4
Special instance methods: toString
Chapter 11 Inheritance and Polymorphism Part 1
Chapter 11 Inheritance and Encapsulation and Polymorphism
Overloading Each method has a signature: its name together with the number and types of its parameters Methods Signatures String toString()
Presentation transcript:

Everything the light touches, Simba, will be yours מבוא למדעי המחשב הורשה – Inheritance מטרת השיעור היא לבחון כיצד התפיסה של מתכנני שפת java את מושג ההורשה מתורגם להתנהגות של מחלקות ואובייקטים. נציג את מושג הפולימורפיזם (שיורחב בהמשך) בשעור זה נכנס לפרטים של הורשה. נברר מה המשמעות של הגדרת שיטות ומשתנים בעלי שם זהה במחלקת האב והבן. עבור כל דוגמה, נשאל: האם הקוד מתקמפל? האם הוא רץ? (לא מתרסק בזמן ריצה) מהי תוצאת הריצה?

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

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

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; this.id = id; numOfCourses= 0; } public int computeTuitionFee(){ return numOfCourses * COURSE_PRICE;

class Student public String getName() {return name;} public int getID() {return id;} public int getNumOfCourses() { return numOfCourses; } public void setNumOfCourses(int numOfCourses) { this.numOfCourses = numOfCourses;

class Student public boolean equals(Object other) { return ((other instanceof Student) && (id == ((Student)other).id)); } public String toString() { return "Student name: " + getName() + ", ID:" + getID() + ", No. of courses: " + getNumOfCourses(); } //class Student

דוגמה: בתוכנית שלנו אנו משתמשים מחלקה Student. התוכנית משתמשת בשיטה public int computeTuitionFee() בכדי לחשב את שכר הלימוד שהסטודנט צריך לשלם, כפונקציה של מספר הקורסים שלו.

דוגמה: עתה, נניח כי אנו מעונינים ליצור מחלקה דומה למחלקה המקורית, במקרה שלנו - סטודנט מילגאי. למחלקה החדשה יש הרבה מן המשותף עם המחלקה המקורית: גם למילגאי שם ות.ז., וגם לו מוגדרת כמות הקורסים אותם הוא לוקח. מאידך, למילגאי נוספת גם גובה המילגה אותה הוא מקבל, ותהליך חישוב שכר הלימוד שלו מעט שונה כי הוא מקבל את המלגה כהנחה על שכר הלימוד. 8

אפשרות ראשונה – שינוי Student אנו יכולים לשנות את המחלקה Student. ניתן להוסיף לכל סטודנט את המילגה שלו (0 במקרה של סטודנט לא מילגאי) ונוסיף את השיטה public int getMilga(); המחזירה את המילגה של הסטודנט.

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

אפשרות שנייה – יצירת מחלקה חדשה לבנות מחלקה חדשה עבור מלגאי: class Milgay{ // cut & paste Student, add more methods, and // change existing methods } חסרונות: שכפול קוד. בנוסף, כל עדכון שנירצה לבצע בעתיד במחלקה Student נאלץ לבצע פעמיים. לא ניתן ליצור מצביע כללי עבור אובייקט שהוא או סטודנט או מילגאי, אלא אם מגדירים ממשק משותף (ואז חזרנו לבעיה הראשונה – יש צורך לשנות ולקמפל מחדש קוד קיים). החיסרון העיקרי של גישה זו הוא בעצם השימוש בשכפול של קוד. שינוי הקוד של המחלקה Student יכריח אותנו לשנותו גם במחלקה Milgay וזהו מצב מועד לתקלות.   אך אל יאוש, מנגנון ההורשה יספק לנו פתרון אידיאלי במקרה זה. (מנגנון ההורשה משמש גם במקרים נוספים, אך על כך נדון בהמשך הקורס)

פתרון בעזרת הורשה: מחלקה Milgay תירש את המחלקה Student: Milgay תקבל "במתנה" את ההתנהגות של Student – ניתן לחשוב על כך כאילו שהשיטות הציבוריות של Student מגדירות ממשק אשר ממומש ע"י Milgay (ולכן ניתן לאמר כי "כל מלגאי הוא גם סטודנט" – "Every Milgay IS A Student". ) עם זאת, Milgay גם מקבלת את מימוש ההתנהגות במתנה – אין צורך לכתוב שנית את קוד השיטות המשותפות. 12

פתרון בעזרת הורשה: מחלקה Milgay תירש את המחלקה Student: ניתן להוסיף ל-Milgay שדות ושיטות נוספים, וכן ניתן "לדרוס" (Overriding) שיטות של Student, ולממש אותן באופן שונה (בדומה למה שראינו לגבי דריסה של equals ו-toString של המחלקה Object) 13

המימוש הטכני: public class Milgay extends Student { private int milga; … המחלקה מילגאי "מרחיבה" את המחלקה סטודנט. ניתן לחשוב על זאת כך: "בתוך כל מילגאי נמצא סטודנט קטן". בנוסף, למלגאי יש שדה milga היחודי רק לו. 14

המימוש הטכני: כאשר בונים מלגאי חדש, יש לבנות גם את הסטודנט שבתוכו. בשביל להפעיל בנאי של מחלקה ממנה ירשנו, נשתמש בצורה super(…): public Milgay(int id, String name, int milga){ super(id, name); this.milga= milga; } בדומה ל-this(…), קריאה ל-super(…) חייבת להיות הפקודה הראשונה בבנאי. ניתן להפעיל כל בנאי של "מחלקת האב". אם לא כתבנו זאת באופן מפורש, תתבצע קריאה לבנאי ללא פרמטרים (ואם לא קיים כזה בנאי – שגיאת קומפילציה!). במקרה שלנו נקרא לבונה שכותרתו: public Student(int id, String name) הקריאה מתבצעת ע"י שימוש במילה השמורה super. כשם ש-this מאפשר לנו פנייה לשדות (שיטות ומשתני מחלקה) של העצם, כך super מאפשר פנייה לשדות שקיבלנו בירושה מהמחלקה האבא.   בחלק של המלגאי אנו פשוט מאתחלים את משתנה המחלקה milga בהתאם לפרמטר שקיבלנו. ??? ומה אם לא היינו קוראים לבונה של Student ע"י שימוש ב-super? !!! ניסינו וקיבלנו מהקומפיילר את הודעת השגיאה הבאה: Implicit super constructor Student() is undefined. Must explicitly invoke another constructor Milgay.java line 5 ??? ומה פשר הודעת השגיאה הזאת? !!! לא ניתן לאתחל מופע של מחלקה יורשת ללא הפעלת הבונה של מחלקת האבא. אם לא כתובה פנייה מפורשת, מוכנסת אוטומטית הפנייה לבונה הריק שכותרתו: public Student() ??? אבל למדנו שאם לא כותבים בונה ריק אז מקבלים כזה באופן אוטומטי! !!! הדבר נכון רק לגבי מחלקות בהן אין בונים אחרים! במחלקה שלנו יש בונים אחרים ולכן הבונה הריק לא מסופק באופן אוטומטי. יש דמיון בין השורה: super(id, name); בבונה של Milgay, לשורה: this(s.getID(), s.getName()); בבונה ההעתקה של המחלקה Student. public Student(Student s) { this(s.getID(),s.getName()); courses = new SetAsArray(s.courses); } כשם שניתן להשתמש במילה השמורה this לצורך קריאה לבונה אחר, כן ניתן להשתמש במילה השומורה super לקריאה לבונה של המחלקה האבא. (בהמשך נראה שימוש נוסף ב-super). 15

המימוש הטכני: … public int getMilga() { return milga; } אין צורך לכתוב את שאר השיטות של סטודנט (getName(), וכו') במחלקה מלגאי – הן יתווספו באופן אוטומטי. מאידך, ברצוננו לעדכן השיטה computeTuitionFee() בכדי שתתאים למלגאי. ניתן לעשות זאת בעזרת מנגנון "הדריסה" (Overriding), כפי שעשינו בעבר עם השיטות equals ו-toString. 16

ניסיון ראשון (שמעצם שמו, ניסיון ראשון, כנראה עתיד להיכשל! ) : // this is the wrong first attempt that fails public int computeTuitionFee(){ return numOfCourses * COURSE_PRICE - milga; } מה הבעיה? במחלקה Milgay אין גישה למשתנים הפרטיים numOfCourses ו-COURSE_PRICE של המחלקה Student. ??? מה הבעיה? !!! לא מתקמפל!   ??? מהי הודעת השגיאה של הקומפיילר? !!! Milgay.java:27: courses has private access in Student return (courses.getSize() * COURSE_PRICE) - milga; Milgay.java:28: COURSE_PRICE has private access in Student כלומר, משתני המחלקה הפרטיים של המחלקה ממנה ירשנו אינם חשופים לשימושינו! באופן דומה לא נוכל לפנות ישירות ל-name ו-id. ??? אז אולי נעשה את courses משתנה מהרשאת public במחלקה Student? !!! זה תכנות לא נכון! לא נעוות את המחלקה ממנה ירשנו כדי שתתאים לדרישותינו. המשתנה courses אינו חלק מהשירותים הציבוריים שהמחלקה Student מציעה! ??? אז איך בכל זאת נתגבר על הבעיה? !!! נראה שתי שיטות!

פתרון: public int computeTuitionFee(){ return Math.max(0, super.computeTuitionFee() – milga); } } //class Milgay באותו אופן כמו ש-this מצביע על האובייקט הקורא לשיטה, super מצביע על "אבייקט האב" אשר ממנו ירשנו. בדוגמה הנוכחית super מצביע על הסטודנט הקטן בתוך המלגאי. ניתן עתה לפנות לשיטות ולמשתנים הציבוריים שלו. נשים לב כי הקריאה super.computeTuitionFee() מפעילה את הקוד הכתוב במחלקה Student. 18

דריסת שיטה של האב נתבונן בשיטה public int computeTuitionFee() השיטה קיימת במחלקה Student, אך במימוש המחלקה Milgay דרסנו (override) שיטה זו וסיפקנו מימוש אלטרנטיבי. המימוש החדש הכתוב במחלקה Milgay הוא זה שיופעל כאשר טיפוס האובייקט המפעיל את השיטה הוא מילגאי. שימו לב כי חתימת השיטה המופיעה במחלקה Milgay חייבת להיות זהה לזו המופיעה במחלקה Student כי אחרת לא נקבל דריסה אלא שתי שיטות נפרדות.   ??? זה נשמע לי מוכר, העניין הזה עם דריסה. !!! נכון! במחלקה Student ובמחלקות אחרות שמימשנו דרסנו את השיטות toString ו-equals של Object.   ??? אבל לא רשמנו class Student extends Object... !!! לא סתם אמרנו את המשפט "כל Student הוא Object". כל מחלקה ב-java יורשת מהמחלקה Object ולכן אין צורך לציין זאת באופן מפורש. ??? האם מחלקה אחת יכולה לרשת משתי מחלקות שונות? !!! לא – ב-java מחלקה יכולה לרשת ממחלקה הורה אחת בלבד. ??? אז האם מלגאי הוא אינו אובייקט? !!! "כל מלגאי הוא סטודנט" וגם "כל סטודנט הוא אובייקט" ומכאן שגם "כל מלגאי הוא אובייקט". המחלקה אובייקט היא שורש עץ הירושה. באופן ציורי, ניתן להמחיש זאת כך:

"מודל הבצל" כאשר פונים לשיטות ציבוריות לא סטטיות של אובייקטים, אזי הקוד שיבוצע נקבע בזמן ריצה ולפי טיפוס האובייקט בפועל (ולא לפי טיפוס המצביע), "מבחוץ פנימה". לכן, ניסיון להפעיל את השיטה getName() על אובייקט מסוג מילגאי יגרום להפעלת השיטה הכתובה במחלקה Student. לעומת זאת, נסיון להפעיל את computeTuitionFee() יפעיל את הקוד במחלקה Milgay. Student getName(), computeTuitionFee(), addCourse(), getID(), etc… Object toString(), equals(…), etc… "בתוך כל אובייקט יושב אובייקט קטן ממחלקת האב, כאשר בגרעין יושב Object". Milgay getMilga(), computeTuitionFee()

מוטיבציה להורשה הורשה מגדירה יחס היררכי בין המחלקות השונות (עץ מחלקות). בראש ההיררכיה נמצאת המחלקה Object (כלומר - אם אנו מגדירים מחלקה שאינה מרחיבה אף מחלקה אחרת, פרוש הדבר הוא שהיא extends Object). לכל מחלקה יש בדיוק מחלקת אב אחת בעץ, מלבד ל-Object הנמצאת בשורש העץ

הורשה מול ממשקים בדומה לממשקים, הורשה מאפשרת להתייחס למופעים ממחלקות שונות באופן אחיד, כאשר מעונינים לפעול על המכנה המשותף שלהם. על אובייקט ממחלקה X יכול להצביע מצביע מכל טיפוס Y, כך ש-Y מחלקה "על המסלול בעץ" מ-X ל-Object. לדוגמה, על אוביקט מהמחלקה Milgay יכולים להצביע מצביעים מהטיפוסים Milgay, Student, ו-Object. בשונה ממשקים, הורשה מאפשרת שיתוף גם במימוש ההתנהגות, כלומר שימוש חוזר בקוד קיים. מחלקה מסוימת יכולה לרשת מחלקה אחת בלבד, בעוד שהיא יכולה לממש מספר ממשקים. 22

הפעלת שיטה שנדרסה המקרה הפשוט הפעלת שיטה שנדרסה המקרה הפשוט public static void main(String[] args) { Milgay m = new Milgay(11,"Moshe", 1000); m.setNumOfCourses(2); System.out.println("The milga of " + m.getName() + ” is " + m.getMilga()); System.out.println("The TF of “ + m.getName() + ” is " + m.computeTuitionFee()); … במקרה זה אנו יודעים כי השיטה computeTuitionFee של המחלקה מלגאי היא שתרוץ. נכתוב פונקציית main נוסיף לה שורות קוד, ולגבי כל שורה נתעניין האם היא מתקמפלת. אם השורה אינה מתקמפלת, ננסה לחשוב מדוע. אם השורה מתקמפלת, ננסה להבין איך תרוץ השורה בזמן ריצה, ובפרט, מה יודפס למסך. נקודה לדיון: השורה האחרונה מפעילה את toString() של Student. יתכן והיינו רוצים לדרוס שיטה זו במחלקה Milgay.

הפעלת שיטה שנדרסה המקרה המסובך הפעלת שיטה שנדרסה המקרה המסובך Student s1 = new Milgay(11,"Dani", 500); s1.setNumOfCourses(2); System.out.println("The TF of s1 is " + s1.computeTuitionFee()); טיפוס המצביע הוא Student, בעוד שטיפוס האובייקט בפועל הוא Milgay. עבור שיטות ציבוריות לא סטטיות (ורק עבורן!!!) השיטה המופעלת נקבעת בזמן ריצה, לפי טיפוס האובייקט בפועל. מבחינת קומפילציה המצביע s1 הוא מסוג Student. ל-Student יש את השיטה computeTuitionFee ולכן זה מתקמפל.   בזמן הריצה השאלה הנשאלת היא מהי המחלקה של המופע עליו אנו עובדים. יש לחזור לרגע יצירת המופע, כלומר לפקודת ה-new שייצרה את המופע. במקרה שלנו הפקודה היא new Milgay(11,"Dani", 500) מרגע זה מתחיל חיפוש אחר חתימה מתאימה, כלומר חתימה מהסוג: computeTuitionFee() החיפוש מתחיל מהשכבה החיצונית ביותר של הבצל, כלומר במחלקה הנפנית, Milgay. במקרה זה השיטה נמצאת במחלקה Milgay וזו השיטה שתרוץ.

הפעלת שיטה יחודית למילגאי Student s1 = new Milgay(11,"Dani", 500); s1.setNumOfCourses(2); System.out.println("The milga of s1 is “ + s1.getMilga()); לא עבר השורה הראשונה מתקמפלת כי מצביע מסוג Student יכול להצביע על כל מופע שהוא is a Student. בקוד כולו לא מתקמפל. נבחן את תהליך הקומפילציה: הקומפיילר שואל: על מי מתבצעת הפעולה? תשובה: s1 שאלה: מאיזה טיפוס הצבעה הוא s1? תשובה: Student (התשובה לשאלה זו תמיד נמצאת בקוד!) שאלה: האם למחלקה Student יש שיטה getMilga()? תשובה:לא!!!   לכן זה לא מתקמפל!!

הפעלת שיטה יחודית למילגאי (מתוקנת) Student s1 = new Milgay(11,"Dani", 500); s1.setNumOfCourses(2); System.out.println("The milga of s1 is “ + ((Milgay) s1).getMilga()); עבר הטיפוס המצביע משתנה ל-Milgay בגלל שעשינו casting. עתה ל-Milgay יש את השיטה getMilga() ולכן הקומפיילר מאשר את זה.

"הם עבדו עלי, דוד" התרסק Student s2 = new Student(11,"Dani"); s2.setNumOfCourses(2); System.out.println("The milga of (the non-milgay) s2 is " + ((Milgay) s2).getMilga());  המשמעות של Casting היא שהמתכנת לוקח על עצמו את האחריות לתקינות הטיפוסים. התרסק נעבור שוב על התהליך של הקומפיילר: הקומפיילר שואל: על מי מתבצעת הפעולה? תשובה: s2 שאלה: מאיזה טיפוס הצבעה הוא s2? תשובה: לאחר ה-casting טיפוס ההצבעה הוא Milgay. שאלה: האם למחלקה Milgay יש שיטה getMilga()? תשובה:כן!!! ולכן זה מתקמפל! ומה קורה בזמן ריצה? התוכנית עפה עם הודאת השגיאה: Exception in thread "main" java.lang.ClassCastException: Student at Lecture16.main(Lecture16.java:30)   ClassCastException פירושו שבזמן ריצה ניסינו לבצע casting ל-Milgay עבור מופע שהוא אינו instanceof Milgay. ??? אז למה הקומפיילר נתן לזה לקרות? !!! לקומפיילר אין את הכלים להתמודד עם המצב הזה. הוא אינו יכול לדעת האם בזמן ריצה ה-casting יהיה חוקי או לא. ניתן לראות ב-casting כסוג של "העברת אחריות" מהקומפיילר למתכנת. הקומפיילר מסכים ל-casting אך "מסיר מעצמו אחריות" לתוצאות בזמן הריצה.

סטטי מול לא-סטטי public class Point{ private double x; private double y; … public void printPoint1(){ System.out.println("(" + x + "," + y + ")"); } public static void printPoint2(Point p){ System.out.println("(" + p.x + "," + p.y + ")"); } //class Point 28 28

סטטי מול לא-סטטי פרוצדורות סטטיות אינן משויכות לאובייקט מסוים, ולכן כאשר מבצעים קריאה לפרוצדורה כזו יש צורך להעביר מידע פנימי על האובייקט עליו היא מופעלת, או הצבעה לאובייקט עצמו. Point p1 = new Point(1,2); Point.printPoint2(p1); פרוצדורות סטטיות משויכות למחלקה מסוימת. למשל, הפונקציות של המחלקה Math. מכיוון שאין הגיון ליצור אובייקט אך ורק בשביל ביצוע פעולה מתמטית (פעולות אלו אינן תלויות במצב של אובייקט כלשהו שיכול להשתנות במהלך הריצה), הפונקציות מוגדרות כסטטיות וכך ניתן להשתמש בהן באופן ישיר (Math.pow(…), Math.random()). נהוג לאגד במחלקה מסוימת אוסף של פרוצדורות סטטיות הקשורות לאותו התחום, ובכך לאפשר שימוש באותו אוסף מתוך מספר רב של תוכניות שונות. לא ניתן לדרוס פרוצדורות סטטיות – הקוד שיופעל נקבע כבר בזמן קומפילציה. Math is a class that contains a collection of mathematical static methods, there is no need to define an object for this. 29 29

סטטי מול לא-סטטי שיטות מחלקה לעומת זאת, משויכות באופן ישיר לאובייקט אשר יזם את הקריאה להן. למשל: public static void printPoint3(Point p){ System.out.println("(" + p.getX() + "," + p.getY() + ")"); } public static void main(String[] args){ Point p = new Point(1,2); p.printPoint1(); printPoint3(p); Point.printPoint2(); //Compilation Error Point.printPoint2(p); p.printPoint2(p); //works – but it is the wrong way to write code שימו לב כי הפרוצדורה הסטטית printPoint2 יכלה לגשת לשדות הפרטיים של הארגומנט p, כיוון שהיא כתובה במחלקה Point. לעומת זאת, pringPoint3 כתובה במחלקה אחרת, והיא יכולה לגשת רק לשיטות הציבוריות של Point. ניתן להפעיל פרוצדורות סטייות גם מתוך אוביקטים (השורה האחרונה), אך זה שקול להפעלתם מתוך המחלקה 30 30

משתנים סטטיים מול שדות כאשר אנו עובדים עם אובייקטים, לכל אובייקט יש את השדות שלו. ב-java יש סוג נוסף של משתנים הנקראים משתנים סטטים. דוגמה למשתנה סטטי: Math.PI בניגוד לשדות, משתנים סטטים משויכים למחלקה עצמה, ולא למופעים שלה. לרוב משתמשים במשתנים סטטים לתיאור קבועים (כדוגמת Math.PI), ואז הם מוגדרים כ-static final. בד"כ לא נשתמש במשתנים מסוג זה באופן אחר, אך בכל זאת: 31

public static int numberOfPoints = 0; public Point(){ x=0; y=0; אם נרצה לדוגמה, למנות את מספר האובייקטים מסוג Point שהוגדרו בתכנית, כלומר לספור את מספר הקריאות שבוצעו לבנאי המחלקה Point, נגדיר משתנה סטטי numberOfPoints , ונגדיל את ערכו בכל קריאה לבנאי: class Point{ public static int numberOfPoints = 0; public Point(){ x=0; y=0; numberOfPoints = numberOfPoints + 1; } … }//class עתה נוכל לכתוב בתכנית: System.out.println(Point.numberOfPoints); וכמובן לכל שאר הבנאים נוסיף את אותה שורה. הערה: בפועל, מספר האובייקטים הקיימים לא זהה בהכרח למספר האובייקטים שנוצרו (java garbage collector), אבל לא נכנס לנושא זה בקורס. דוגמה נוספת למשתנים סטטיים תינתן בתירגול. 32