תוכנה 1 בשפת Java שיעור מספר 13: "המשך הורשה, אוספים גנריים וסיכום"

Slides:



Advertisements
Similar presentations
Transparency No. 1 Java Collection API : Built-in Data Structures for Java.
Advertisements

Chapter 6 The Collections API. Simple Container/ Iterator Simple Container Shape [] v = new Shape[10]; Simple Iterator For( int i=0 ; i< v.length ; i++)
INTERFACES IN JAVA 1.Java Does not support Multiple Inheritance directly. Multiple inheritance can be achieved in java by the use of interfaces. 2.We need.
Sadegh Aliakbary Sharif University of Technology Fall 2012.
Sadegh Aliakbary. Copyright ©2014 JAVACUP.IRJAVACUP.IR All rights reserved. Redistribution of JAVACUP contents is not prohibited if JAVACUP.
Stacks, Queues, and Deques
Stacks. What is a stack? Last-in first-out data structure (LIFO) New objects are placed on top Removal restricted to top object Examples?
Unit 11 1 Unit 11: Data Structures H We explore some simple techniques for organizing and managing information H This unit focuses on: Abstract Data Types.
1 CSCD 326 Data Structures I Stacks. 2 Data Type Stack Most basic property: last item in (most recently inserted) is first item out LIFO - last in first.
24-Jun-15 Introduction to Collections. 2 Collections A collection is a structured group of objects Java 1.2 introduced the Collections Framework Collections.
CHAPTER 6 Stacks Array Implementation. 2 Stacks A stack is a linear collection whose elements are added and removed from one end The last element to be.
Liang, Introduction to Java Programming, Sixth Edition, (c) 2007 Pearson Education, Inc. All rights reserved L15 (Chapter 22) Java Collections.
Java's Collection Framework
Building Java Programs Interfaces, Comparable reading: , 16.4, 10.2.
Collections. Why collections? Collections are used to hold a collection of objects. List holds objects based on order of insertion and can hold non unique.
Geoff Holmes and Bernhard Pfahringer COMP206-08S General Programming 2.
Abstract Data Types (ADTs) and data structures: terminology and definitions A type is a collection of values. For example, the boolean type consists of.
Chapter 7 Stacks I CS Data Structures I COSC 2006 April 22, 2017
Collections F The limitations of arrays F Java Collection Framework hierarchy  Use the Iterator interface to traverse a collection  Set interface, HashSet,
Java™ How to Program, 9/e Presented by: Dr. José M. Reyes Álamo © Copyright by Pearson Education, Inc. All Rights Reserved.
Effective Java: Generics Last Updated: Spring 2009.
1 Java: AP Curriculum Focus and Java Subset Alyce Brady.
© 2004 Goodrich, Tamassia Stacks. © 2004 Goodrich, Tamassia Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data.
Some Other Collections: Bags, Sets, Queues and Maps COMP T2 Lecture 4 School of Engineering and Computer Science, Victoria University of Wellington.
1 Stacks. 2 A stack has the property that the last item placed on the stack will be the first item removed Commonly referred to as last-in, first-out,
תוכנה 1 תרגול 8 – מבני נתונים גנריים. 2 Java Collections Framework Collection: a group of elements Interface Based Design: Java Collections Framework.
Information and Computer Sciences University of Hawaii, Manoa
1 Collections Framework A collections framework is a unified architecture for representing and manipulating collections. All collections frameworks contain:
CSE 143 Lecture 20 Abstract classes. 2 Circle public class Circle { private double radius; public Circle(double radius) { this.radius = radius; } public.
Recitation 5 Enums and The Java Collections classes/interfaces 1.
Some Other Collections: Bags, Sets, Queues and Maps COMP T2 Lecture 4 School of Engineering and Computer Science, Victoria University of Wellington.
Java Programming Persistent Data Types. Persistent Data Structure A persistent data structure is a data structure having an internal state that never.
3-1 Java's Collection Framework Another use of polymorphism and interfaces Rick Mercer.
David Stotts Computer Science Department UNC Chapel Hill.
Building Java Programs Interfaces reading: , 16.4.
CSE 143 Lecture 14 Interfaces; Abstract Data Types (ADTs)
Modern Programming Tools And Techniques-I
Sections 3.4 Formal Specification
Lecture 13: Interfaces, Comparable reading: , 16.4, 10.2
Sixth Lecture ArrayList Abstract Class and Interface
Compsci 201 Midterm 1 Review
Chapter 19 Java Data Structures
Software Development Java Collections
Recitation 11 Lambdas added to Java 8.
Exceptions, Interfaces & Generics
Stacks.
Road Map CS Concepts Data Structures Java Language Java Collections
Advanced Programming Behnam Hatami Fall 2017.
Introduction to Collections
Introduction to Collections
תוכנה 1 בשפת Java שיעור מספר 10: חידושים ב Java 8
null, true, and false are also reserved.
Object-Oriented Programming
نوع داده هاي انتزاعي Abstract Data Types
תוכנה 1 בשפת Java שיעור מספר 9: "ירושה נכונה" (הורשה II)
Modeling with Inheritance
תוכנה 1 בשפת Java שיעור מספר 11: חידושים ב Java 8
Introduction to Collections
Advanced Programming in Java
CSE 1030: Implementing Non-Static Features
Introduction to Collections
Introduction to Collections
Generics, Lambdas, Reflections
CSE 373 Implementing a Stack Reading: Weiss Ch. 3; 3.6; 1.5
slides created by Alyssa Harding
slides created by Marty Stepp
Agenda Types and identifiers Practice Assignment Keywords in Java
Lecture 16 Stacks and Queues CSE /26/2018.
A type is a collection of values
Presentation transcript:

תוכנה 1 בשפת Java שיעור מספר 13: "המשך הורשה, אוספים גנריים וסיכום" בית הספר למדעי המחשב אוניברסיטת תל אביב

היום בשיעור קבלנות משנה (הורשה והחוזה) – המשך משיעור 12. תבנית העיצוב Bridge – חזרה והרחבה המשך מוזרויות ב Java אוספים גנריים בחינה תוכנה 1 בשפת Java אוניברסיטת תל אביב

קבלנות משנה משהבנו את ההיגיון שבבסיס יחסי ספק, לקוח וקבלן משנה, ניתן להסביר את חוקי שפת Java לגבי השינויים הבאים שקבלן המשנה יכול לבצע: שינוי ההצהרה על חריגים שינוי נראות שינוי הערך המוחזר The list of exceptions that may be thrown is a pre-condition In the override method it can be weaken (subset of the list) תוכנה 1 בשפת Java אוניברסיטת תל אביב

הורשה וחריגים קבלן משנה (מחלקה יורשת [מממשת], הדורסת [מממשת] שרות) אינו יכול לזרוק מאחורי הקלעים חריג שלא הוגדר בשרות הנדרס [או במנשק] למתודה הדורסת [המממשת] מותר להקל על הלקוח ולזרוק פחות חריגים מהמתודה במחלקת הבסיס שלה [במנשק] לדוגמא: בהנתן מימוש המחלקה A, אילו מבין הגירסאות של func ניתן להוסיף ל B שיורשת מ A? public class A{ public void func() throws IOException{ } } public class B extends A{ //public void func() {} //public void func() throws IOException {} //public void func() throws EOFException{} //public void func() throws Exception{} The list of exceptions that may be thrown is a pre-condition In the override method it can be weaken (subset of the list)     תוכנה 1 בשפת Java אוניברסיטת תל אביב

הורשה וניראות למתודה הדורסת [המממשת] מותר להקל את הנראות – כלומר להגדיר סטטוס נראות רחב יותר, אבל אסור להגדיר סטטוס נראות מצומצם יותר. לדוגמא: בהנתן מימוש המחלקה A, אילו מבין הגירסאות של func ניתן להוסיף ל B שיורשת מ A? public class A{ protected void func(){ } } public class B extends A{ //public void func(){ } //protected void func() {} //void func() {} //private void func() {}     תוכנה 1 בשפת Java אוניברסיטת תל אביב

הורשה והערך המוחזר למתודה הדורסת [המממשת] מותר לצמצם את טיפוס הערך המוחזר, כלומר טיפוס הערך המוחזר הוא תת טיפוס של טיפוס הערך המוחזר במתודה במחלקת הבסיס שלה [במנשק] לדוגמא: בהנתן מימוש המחלקה A, אילו מבין הגירסאות של func ניתן להוסיף ל B שיורשת מ A? public class A{ public Number func() { return null; } } public class B extends A{ //public Object func() { return null; } //public Number func() { return null; } //public Integer func() { return null; }    תוכנה 1 בשפת Java אוניברסיטת תל אביב

תנאי קדם מופשט מהי ההיררכיה בין 3 המחלקות: מחסנית, מחסנית חסומה, מחסנית בלתי חסומה ? מה יהיה תנאי הקדם של המתודה push במחלקה מחסנית? מחסנית מחסנית בלתי חסומה מחסנית חסומה תוכנה 1 בשפת Java אוניברסיטת תל אביב

תנאי קדם מופשט תנאי הקדם לא יכול להיות ריק (TRUE) כי אז הוא יחוזק ע"י המחסנית החסומה תנאי הקדם צריך להיות !full() כאשר full() היא מתודה מופשטת (או מתודה המחזירה תמיד false). המחלקה מחסנית חסומה" תממש אותה כך שתחזיר count()==capacity() תנאי קדם המכיל מתודות מופשטות או מתודות שנדרסות במורד עץ ההורשה נקרא תנאי קדם מופשט למרות שתנאי הקדם הקונקרטי אכן מתחזק ע"י המחסנית החסומה תנאי הקדם המופשט נשאר ללא שינוי תוכנה 1 בשפת Java אוניברסיטת תל אביב

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

ראייה לטווח רחוק האבולוציה של היררכית מחלקות כלי הרכב לא מתחילה בגזירת מחלקות קונקרטיות שיירשו מ VEHICLE הגיוני יותר שבמהלך מימוש ו\או עיצוב המחלקות CAR ו- AIRPLANE נגלה שיש להן הרבה מן המשותף, וכדי למנוע שכפול קוד ניצור מחלקה שלישית - VEHICLE שתכיל את החיתוך של שתיהן אף כלי רכב אינו רק VEHICLE בראייה זו, אין זה מוגזם לדרוש ממחלקה מופשטת ניסוח תנאי קדם מופשט תוכנה 1 בשפת Java אוניברסיטת תל אביב

דוגמא מהו תנאי הקדם של המתודה go() של המחלקה VEHICLE ? CAR BICYCLE מהו תנאי הקדם של המתודה go() של המחלקה VEHICLE ? על פניו – אין כל תנאי קדם לפעולה מופשטת מה עם המחלקה CAR ? – לה בטח יש דרישות כגון hasFuel() מה עם המחלקה BICYCLE ? – לה בטח יש דרישות כגון hasAir() איך VEHICLE תגדיר תנאי קדם ל go() גם כללי מספיק וגם שלא יחוזק ע"י אף אחד מיורשותיה? תוכנה 1 בשפת Java אוניברסיטת תל אביב

פתרון מתודה בולאנית כגון canGo() תעשה את העבודה VEHICLE CAR BICYCLE מתודה בולאנית כגון canGo() תעשה את העבודה המתודה תוגדר כמחזירה TRUE עבור VEHICLE (או שתוגדר כ abstract), ועבור כל אחת מיורשותיה תידרס ותוגדר לפי מה שמתאים במחלקה האמורה בעצם המתודה go() היתה צריכה להיקרא "go_because_you_can()" וכך לא היתה כל הפתעה בתנאי הקדם "המוזר" תוכנה 1 בשפת Java אוניברסיטת תל אביב

הורשה זה רע? הורשה היא מנגנון אשר חוסך קוד ספק פרט למנגנון הרב-צורתיות (polymorphism) הורשה היא סוכר תחבירי של הכלה ואינה הכרחית במקום ש B יירש מ-A , ל- B יכולה להיות התכונה A (שדה) יחסי הורשה נכונים הם דבר עדין יחס is-a לעומת יחס is-part-of או has-a לעומת זאת To be is also to have אבל לא להיפך (משאית היא מכונית כלומר חלק בה הוא מכונית) לפעמים נוח לשאול "האם יכולים להיות לו שניים?" לדוגמא: למכונית יש מנוע, האם יכולה להיות מכונית עם שני מנועים הורשה או מופע? האם Washington יורשת מ- State? תוכנה 1 בשפת Java אוניברסיטת תל אביב

הכוח משחית על המחלקה היורשת לקיים את 2 העקרונות: יחס is-a עקרון ההחלפה אי שמירה על כך תגרום לעיוותים במערכת התוכנה לדוגמא: ננסה לבטא את יחס המחלקות Rectangle ו- Square בעזרת הורשה תוכנה 1 בשפת Java אוניברסיטת תל אביב

מלבן לא יורש מריבוע ברור כי העיצוב לקוי – Rectangle is NOT a Square לא מתקיים יחס is-a public class Square { protected double length; public double getLength(){ return length; } public double getWidth(){ public double area(){ return length*length; ... public class Rectangle extends Square { protected double width; public double getWidth(){ return width; } public double area(){ return length*width; ... ברור כי העיצוב לקוי – Rectangle is NOT a Square למשל המשתמר של Square צריך להכיל את getLength()==getWidth() וברור כי Rectangle לא שומר על כך תוכנה 1 בשפת Java אוניברסיטת תל אביב

אז אולי ריבוע יורש ממלבן ? לא מתקיים עקרון ההחלפה! public class Rectangle { protected double width; protected double length; public double getWidth(){ return width; } public double getLength(){ return length; public double area(){ return length*width; public static void widen(Rectangle rect, double delta){ rect.width += delta; ... מתקיים יחס is-a (ריבוע הוא מלבן) אבל במימוש הספציפי הזה לא מתקיים עקרון ההחלפה. לא ניתן להשתמש בריבוע בכל הקשר שבו ניתן היה להשתמש במלבן זה מפתיע – מכיוון שמתמטית ריבוע הוא סוג של מלבן אז איך בכל זאת נממש את המחלקות ריבוע ומלבן? בעולם התוכנה יש לעשות "ויתורים כואבים" תוכנה 1 בשפת Java אוניברסיטת תל אביב

תבנית העיצוב Bridge - הרחבה תוכנה 1 בשפת Java אוניברסיטת תל אביב

סוגי מחסניות: עוד סוגי מחסניות: AbstStack ArrayListStack LinkedListStack StackedStack AbstStack BoundedStack LastModifiedStack SumStack תוכנה 1 בשפת Java אוניברסיטת תל אביב

AbstStack ArrayListStack LinkedListStack StackedStack Bounded LastModified ArrayList Stack Sum ArrayList Stack Bounded Stacked Stack LastModified Stacked Stack Sum Stacked Stack Bounded LinkedList Stack LastModified LinkedList Stack Sum LinkedList Stack תוכנה 1 בשפת Java אוניברסיטת תל אביב

Bridge Design Pattern - תרשים מחלקות - SimpleStack IStackImpl יחס הכלה . תוכנה 1 בשפת Java אוניברסיטת תל אביב

בשבוע שעבר ראינו את העיצוב הבא: מתאר התנהגות (Bounded, LastModified) public interface IStack<T> { public void push (T e); public void pop (); public T top (); } מתאר מימוש (ArrayList, LinkedList) public interface IStackImpl<T> { public void insert(T e); public void remove(); public T get(int index); } תוכנה 1 בשפת Java אוניברסיטת תל אביב

המחלקה SimpleStack מכילה שדה מטיפוס IStackImpl שבעצם מייצג את המימוש. public class SimpleStack<T> implements IStack<T> { private IStackImpl<T> impl; // MyArrayList or MyLinkedList public SimpleStack(IStackImpl<T> impl) { this.impl = impl; } public void pop() { impl.remove(); } public void push(T e) { impl.insert(e); } public T top() { return impl.get(0);} המחלקה SimpleStack מכילה שדה מטיפוס IStackImpl שבעצם מייצג את המימוש. המחלקות Bounded/LastModifiedStack יורשות מ SimpleStack. איך יראה לקוח טיפוסי שמעוניין ליצור מופע של מחסנית? SimpleStack<Integer> stack = new SimpleStack<Integer> (new ArrayListStackImpl<Integer>()); תוכנה 1 בשפת Java אוניברסיטת תל אביב

תבנית העיצוב Bridge אז מה יש לנו עד כה? שני מנשקים שמאפשרים לנו לייצר כל שילוב בין התנהגות למימוש. הגדרת המנשק IStackImpl מעט מלאכותית, ואף מאפשרת באגים מכיוון שאנחנו מאפשרים למשתמש לגשת למיקומים. נראה שהיה נכון להגדיר ב IStackImpl בדיוק את אותם השירותים שיש ב IStack. מצד שני – אנחנו רוצים לשמור על שני מנשקים שונים עצמאיים. כל מחסנית צריכה להיות הרכבה של IStack עם IStackImpl תוכנה 1 בשפת Java אוניברסיטת תל אביב

עיצוב חדש public interface IStackBase<T>{ public void push (T e); public void pop (); public T top (); } public interface IStack<T> extends IStackBase<T>{ public interface IStackImpl<T> extends IStackBase<T>{ מתאר התנהגות (Bounded, LastModified) מתאר מימוש (ArrayList, LinkedList) תוכנה 1 בשפת Java אוניברסיטת תל אביב

עיצוב חדש public class SimpleStack<T> implements IStack<T> { private IStackImpl<T> impl; // MyArrayList or MyLinkedList public SimpleStack(IStackImpl<T> impl) { this.impl = impl; } public void pop() { impl.pop(); } public void push(T e) { impl.push(e); } public T top() { return impl.top();} תוכנה 1 בשפת Java אוניברסיטת תל אביב

עיצוב חדש public class ArrayListStackImpl<E> implements IStackImpl<E> { ArrayList<E> rep = new ArrayList<E>(); public E top() { return rep.get(rep.size()-1); } public void push(E e) { rep.add(e); } public void pop() { rep.remove(rep.size()-1); } } תוכנה 1 בשפת Java אוניברסיטת תל אביב

עיצוב חדש בעיצוב החדש אנחנו שומרים על כך ש: האם מימשנו ירושה מרובה? כל מחסנית היא הרכבה של התנהגות (IStack) ושל מימוש (IStackImpl) מימוש יציב יותר – פחות פתח לבאגים בשונה מהעיצוב הקודם של IStackImpl תודות להכמסה טובה יותר של IStackImpl האם מימשנו ירושה מרובה? לא! אמנם אנחנו עושים שימוש חוזר בקוד של שתי מחלקות, אחת להתנהגות ואחת למימוש, כל מחסנית שנגדיר יורשת רק ממחלקה אחת. תוכנה 1 בשפת Java אוניברסיטת תל אביב

עיצוב חדש המחסנית stack מקיימת יחס is-a רק עם SimpleStack. SimpleStack<Integer> stack = new SimpleStack<Integer> (new ArrayListStackImpl<Integer>()); המחסנית stack מקיימת יחס is-a רק עם SimpleStack. למעשה, אין שום דרך לדעת שהמימוש הפנימי הוא ArrayListStackImpl. ואם זה מאוד חשוב לנו? תוכנה 1 בשפת Java אוניברסיטת תל אביב

עיצוב חדש נוסיף מנשק חדש שתפקידו לציין שהמחלקה ממומשת באמצעות ArrayList public interface IArrayListImpl{ } public class SimpleArrayListStack<T> extends SimpleStack<T> implements IArrayListImpl{ public SimpleArrayListStack() { super(new ArrayListStackImpl<>()); תוכנה 1 בשפת Java אוניברסיטת תל אביב

עיצוב חדש חסרונות: ריבוי מחלקות קונקרטיות: עבור כל הרכבה של מימוש והתנהגות נצטרך להגדיר מחלקה משלו. ריבוי מנשקים: לכל מימוש נצטרך להגדיר מנשק ריק משלו. יתרונות: מחסנית הממומשת באמצעות ArrayList, ללא תלות בהתנהגות, תקיים יחס is-a עם IArrayListImpl ניתן למשל לשלוח אותה לפונק' שמטפלת במחסניות הממומשות באמצעות ArrayList תוכנה 1 בשפת Java אוניברסיטת תל אביב

האם קיבלנו ירושה מרובה? קרוב, אבל לא. המחסנית SimpleArrayListStack מקיימת יחס is-a עם: המחלקה SimpleStack עם המנשק IArrayListImpl אם היתה ירושה מרובה אמיתית, היה מתקיים יחס is-a עם ArrayListStackImpl תוכנה 1 בשפת Java אוניברסיטת תל אביב

מוזרויות ב Java תוכנה 1 בשפת Java אוניברסיטת תל אביב

priv in Base pub in Sub מה יודפס? public class Base { private void priv() { System.out.println("priv in Base"); } public void pub() { System.out.println("pub in Base"); } public void foo() { priv(); pub(); { public class Sub extends Base { private void priv() { System.out.print ln("priv in Sub"); } public void pub() { System.out.println("pub in Sub"); } { public class Test { public static void main(String[] args) { Base b = new Sub(); b.foo(); } { מה יודפס? priv in Base pub in Sub תוכנה 1 בשפת Java אוניברסיטת תל אביב

שדות, הורשה וקישור סטטי גם קומפילציה של התייחסויות לשדות מתבצעת בצורה סטטית מחלקה יורשת יכולה להגדיר שדה גם אם שדה בשם זה היה קיים במחלקת הבסיס (מאותו טיפוס או טיפוס אחר) public class Base { public int i = 5; } public class Test { public static void main(String[] args) { Base bb = new Base(); Sub ss = new Sub(); Base bs = new Sub(); System.out.println(bb.i); System.out.println(ss.i); System.out.println(bs.i); } public class Sub extends Base { public String i = "five"; } 5 five מה יודפס? תוכנה 1 בשפת Java אוניברסיטת תל אביב

העמסה והורשה Rectangle r = new ColoredRectangle (); במקרים של העמסה הקומפיילר מחליט איזו גרסה תרוץ (יותר נכון: איזו גרסה לא תרוץ) זה נראה סביר (הפרוצדורות מתוך java.lang.String): static String valueOf(double d) {…} static String valueOf(boolean b) {…} אבל מה עם זה? overloaded(Rectangle x) {…} overloaded(ColoredRectangle x) {…} לא נורא, הקומפיילר יכול להחליט, Rectangle r = new ColoredRectangle (); ColoredRectangle cr = new ColoredRectangle (); overloaded(r); // we must use the more general method overloaded(cr); // The more specific method applies תוכנה 1 בשפת Java אוניברסיטת תל אביב

העמסה והורשה אבל זה כבר מוגזם: overTheTop(Rectangle x, ColoredRectangle y) {…} overTheTop(ColoredRectangle x, Rectangle y) {…} ColoredRectangle a = new ColoredRectangle (); ColoredRectangle b = new ColoredRectangle (); overTheTop(a, b); ברור שנדרשת המרה (casting)אבל של איזה פרמטר? a או b? אין דרך להחליט; הפעלת השגרה לא חוקית בג'אווה תוכנה 1 בשפת Java אוניברסיטת תל אביב

העמסה והורשה - שבריריות overTheTop(Rectangle x, ColoredRectangle y) {…} overTheTop(ColoredRectangle x, Rectangle y) {…} ColoredRectangle a = new ColoredRectangle (); ColoredRectangle b = new ColoredRectangle (); overTheTop(a, b); אם הייתה רק הגרסה הירוקה, הקריאה לשגרה הייתה חוקית כאשר מוסיפים את הגרסה הסגולה, הקריאה נהפכת ללא חוקית; אבל הקומפיילר לא יגלה את זה אם זה בקובץ אחר, והתוכנית תמשיך לעבוד, ולקרוא לגרסה הירוקה לא טוב שקומפילציה רק של קובץ שלא השתנה תשנה את התנהגות התוכנית; זה מצב שברירי תוכנה 1 בשפת Java אוניברסיטת תל אביב

העמסה והורשה - יותר גרוע class B { overloaded(Rectangle x) {…} } class S extends B { overloaded(Rectangle x) {…} // override overloaded(ColoredRectangle x) {…} // overload but no override! S o = new S(); ColoredRectangle cr = ... o.overloaded( cr ); // invoke the purple ((B) o).overloaded( cr ) // What to invoke? תוכנה 1 בשפת Java אוניברסיטת תל אביב

עבור הקריאה((B) o).overloaded( cr ) תיבחר (בזמן קומפילציה) החתימה: class B { overloaded(Rectangle x) {…} } class S extends B { overloaded(Rectangle x) {…} // override overloaded(ColoredRectangle x) {…} // overload but no override! S o = new S(); ColoredRectangle cr = ... o.overloaded( cr ); // invoke the purple ((B) o).overloaded( cr ) // What to invoke? מנגנון ההעמסה הוא סטטי: בוחר את החתימה של השרות (טיפוס העצם, שם השרות, מספר וסוג הפרמטרים), אבל עדיין לא קובע איזה שירות ייקרא. עבור הקריאה((B) o).overloaded( cr ) תיבחר (בזמן קומפילציה) החתימה: B.overloaded(Rectangle) בגלל שיעד הקריאה הוא מטיפוס B השרות היחיד הרלבנטי הוא האדום! בזמן ריצה מופעל מנגנון השיגור הדינמי, שבוחר בין השרותים בעלי חתימה זאת, את המתאים ביותר, לטיפוס הדינמי של יעד הקריאה. הטיפוס הדינמי הוא S , לכן נבחר השרות הירוק. כנ"ל אם הקריאה היא: B b = new S(); b.overloaded( cr ) תוכנה 1 בשפת Java אוניברסיטת תל אביב

העמסה זה רע אם עוד לא השתכנעתם שהעמסה היא רעיון מסוכן, אז עכשיו זה הזמן בייחוד כאשר ההעמסה היא ביחס לטיפוסים שמרחיבים זה את זה, לא זרים לחלוטין יוצר שבריריות, קוד שמתנהג בצורה לא אינטואיטיבית (השירות שעצם מפעיל תלוי בטיפוס ההתייחסות לעצם ולא רק במחלקה של העצם), וקושי לדעת איזה שירות בדיוק מופעל ומכיוון שהתמורה היחידה (אם בכלל) היא אסתטית, לא כדאי תוכנה 1 בשפת Java אוניברסיטת תל אביב

שאלות מהקהל וחזרה תוכנה 1 בשפת Java אוניברסיטת תל אביב

מה יודפס? List<Integer> ints = Arrays.asList(1,2,3,4,5); ints.stream().map(x->{ System.out.println("mapping " + x); return x*x; }) .filter(x->{ System.out.println("filtering: " + x); return x>10; .forEach(x->{ System.out.println("terminating: " + x); }); output: mapping 1 filtering: 1 mapping 2 filtering: 4 mapping 3 filtering: 9 mapping 4 filtering: 16 terminating: 16 mapping 5 filtering: 25 terminating: 25 מה יודפס? תוכנה 1 בשפת Java אוניברסיטת תל אביב

מה ישתנה אם נבצע את פעולת ה filter אחרי פעולת ה sort? public static int comparesCounter; public static void main(String[] args) { List<Integer> ints = Arrays.asList(5,4,3,2,1,6); ints.stream() .filter(x->x%2==0) .peek(x->{System.out.println("peek " + x);}) .sorted((x,y)->{ comparesCounter++; System.out.println("comparing: " + x + "," + y); return Integer.compare(x, y); }) .forEach(System.out::println); System.out.println("num of compares: " + comparesCounter); } output: peek 4 peek 2 peek 6 comparing: 2,4 comparing: 6,2 comparing: 6,4 2 4 6 num of compares: 3 הפעולה peek מחזירה את הזרם עליו היא מופעלת, ובנוסף, מפעילה על כל איברי הזרם את הפעולה שקיבלה כפרמטר. הפעולה sorted אינה פעולה שגרתית. על מנת לבצע אותה, יש לאסוף את כל אברי הזרם עליו היא מופעלת! מה ישתנה אם נבצע את פעולת ה filter אחרי פעולת ה sort? תוכנה 1 בשפת Java אוניברסיטת תל אביב

האם בלוק ה finally יתבצע? כמובן! נשאלת השאלה: מתי? public class Test{ public static void main(String[] args) { func("abc"); } public static SimpleClass func(Object i) { try { String str = (String)i; return new SimpleClass(str); finally { System.out.println("finally!"); public static class SimpleClass{ public SimpleClass(String str) { System.out.println("*: " + str); האם בלוק ה finally יתבצע? כמובן! נשאלת השאלה: מתי? לפני שהמחסנית משחררת את הפונקציה. ערך ההחזרה נוצר לפני שמתבצע בלוק ה finally. תוכנה 1 בשפת Java אוניברסיטת תל אביב

אילו מבין הפונקציות מפרות את שמורת המחלקה? /** * @inv !isEmpty() implies top() != null */ public class SectionA { private final LinkedList<Object> elements = new LinkedList<Object>(); * @post !isEmpty() * @post top() == o public void push(Object o){ elements.add(o); } * @pre !isEmpty() * @post @return == top()@pre public Object pop(){ final Object popped = top(); elements.removeLast(); return popped; שאלה מתרגיל בית 6: אילו מבין הפונקציות מפרות את שמורת המחלקה? הפונקציה push מפרה את השמורה. לאחר השימוש ב push יכול להיווצר מצב שבו top מחזירה null למרות שהמחסנית אינה ריקה תוכנה 1 בשפת Java אוניברסיטת תל אביב

הפונק’ top תפר את השמורה רק אם יש null במחסנית. /** * @inv !isEmpty() implies top() != null */ public class SectionA { //previous methods //*** * @pre !isEmpty() * @post @return != null public Object top(){ return elements.getLast(); } * * @post @return == true iff elements.size() > 0 public boolean isEmpty(){ return elements.size() == 0; הפונק’ top תפר את השמורה רק אם יש null במחסנית. איך ה null הגיע לשם? אם push ממומשת נכון, זה לא יכול לקרות. תוכנה 1 בשפת Java אוניברסיטת תל אביב

אוספים גנריים תוכנה 1 בשפת Java אוניברסיטת תל אביב

HashSet class Point{ int x; int y; public Point(int x, int y) { this.x = x; this.y = y; } Set<Point> points = new HashSet<>(); Point p1 = new Point(1,2); Point p2 = new Point(1,2); points.add(p1); points.add(p2); System.out.println(points.size()); Output: 2 תוכנה 1 בשפת Java אוניברסיטת תל אביב

? HashSet איך עובדת הכנסה ל HashSet? Point: 1,4 Point: 9,3 Point: 3,0 Point: 1,4 Point: 9,3 Point: 3,0 1 ? 2 Point: 2,5 Point: 9,3 3 4 5 5 Point: 3,9 Point: 5,2 תוכנה 1 בשפת Java אוניברסיטת תל אביב

HashSet איך עובדת הכנסה ל HashSet? hashCode Point: 1,4 Point: 9,3 Point: 1,4 Point: 9,3 Point: 3,0 1 2 Point: 2,5 Point: 9,3 3 4 5 5 Point: 3,9 Point: 5,2 תוכנה 1 בשפת Java אוניברסיטת תל אביב

HashSet איך עובדת הכנסה ל HashSet? Point: 9,3 equals Point: 1,4 Point: 1,4 Point: 9,3 Point: 3,0 1 2 Point: 2,5 3 4 5 5 Point: 3,9 Point: 5,2 תוכנה 1 בשפת Java אוניברסיטת תל אביב

HashSet דרישות מהמימוש של hashCode: אם שני אובייקטים x ו y מקיימים x.equals(y), הפונקציה hashCode צריכה להחזיר את אותו הערך עבור שניהם כדאי לייצר ערכים שונים עבור אובייקטים x ו y שאינם מקיימים x.equals(y) על מנת לשפר ביצועים. ייצור ערכים זהים יפגע רק בביצועים, לא בנכונות. תוכנה 1 בשפת Java אוניברסיטת תל אביב

HashSet כדאי לתת ל eclipse לחולל לבד את המימוש של hashCode, ביחד עם המימוש של equals. צריך לוודא שמעדכנים את שני המימושים כאשר יש שינוי באובייקטים (למשל, מתווספים או מוסרים שדות). HashMap – עובד בדיוק באותו האופן. תוכנה 1 בשפת Java אוניברסיטת תל אביב

TreeSet Set<Point> points = new TreeSet<>( (a,b)->Integer.compare(a.x, b.x)); Point p1 = new Point(1,2); Point p2 = new Point(1,2); points.add(p1); points.add(p2); System.out.println(points.size()); Output: 1 חייבים לשלוח Comparator כיוון ש Point אינה Comparable תוכנה 1 בשפת Java אוניברסיטת תל אביב

TreeSet Set<Point> points = new TreeSet<>( (a,b)->Integer.compare(a.x, b.x)); Point p1 = new Point(1,2); Point p2 = new Point(1,2); Point p3 = new Point(1,3); points.add(p1); points.add(p2); points.add(p3); System.out.println(points.size()); Output: 1 תוכנה 1 בשפת Java אוניברסיטת תל אביב

TreeSet TreeSet אינו עובד עם hashCode (הגיוני, בשביל זה יש HashSet). TreeSet אינו עובד עם equals (זה קצת מפתיע). המימוש של compare/compareTo (תלוי אם האלמנטים הם Comparable או שמשתמשים ב Comparator) חייב להיות עקבי עם equals. אחרת – נוכל לגלות ששני אובייקטים שאינם equals נחשבים כזהים ע"י ה TreeSet. תוכנה 1 בשפת Java אוניברסיטת תל אביב

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

תודה! תוכנה 1 בשפת Java אוניברסיטת תל אביב