Πανεπιστήμιο Πειραιά Τμήμα Ψηφιακών Συστημάτων Αντικειμενοστρεφής Προγραμματισμός 30/4/2018 Δρ. Ανδριάνα Πρέντζα Αναπληρώτρια Καθηγήτρια aprentza@unipi.gr
Τα πλεονεκτήματα της κληρονομικότητας Αποφυγή πανομοιότυπων τμημάτων κώδικα: η χρήση της κληρονομικότητας εξαλείφει την ανάγκη να γράφουμε πανομοιότυπα ή πολύ όμοια τμήματα κώδικα δύο φορές (ή ακόμα περισσότερες). Επαναχρησιμοποίηση κώδικα: μπορούμε να χρησιμοποιούμε εκ νέου υπάρχοντα κώδικα. Αν υπάρχει ήδη μια κλάση παρόμοια με αυτή που χρειαζόμαστε, μπορούμε ορισμένες φορές να δηλώσουμε την υπάρχουσα κλάση και ως υποκλάση, και να επαναχρησιμοποιήσουμε τμήμα του υπάρχοντος κώδικα, αντί να υλοποιούμε τα πάντα ξανά. Ευκολότερη συντήρηση: διευκολύνεται η συντήρηση της εφαρμογής, αφού η σχέση μεταξύ των κλάσεων εκφράζεται με σαφήνεια. Κάποια αλλαγή σε ένα πεδίο ή μια μέθοδο που μοιράζεται μεταξύ διαφορετικών τύπων υποκλάσεων χρειάζεται να γίνει μόνο μία φορά. Επεκτασιμότητα: η χρήση της κληρονομικότητας, καθιστά πολύ ευκολότερη την επέκταση μιας υπάρχουσας εφαρμογής με συγκεκριμένους τρόπους.
Η κλάση Object Η κλάση java.lang.object είναι η superclass όλων των κλάσεων! Αν μία κλάση δεν λέει ρητά από ποια κλάση προκύπτει, τότε προκύπτει από την κλάση Object
Η κλάση Object Όλες οι κλάσεις στη Java κληρονομούν έμμεσα ή άμεσα από την κλάση Object (πακέτο java.lang ), συνεπώς οι 11 μέθοδοί της κληρονομούνται από όλες τις άλλες κλάσεις! Οι μέθοδοι της κλάσης Object clone equals finalize getclass hashcode notify, notifyall, wait tostring 2005 Pearson Education, Inc. All rights reserved.
Η κλάση Object Method Description Clone This protected method, which takes no arguments and returns an Object reference, makes a copy of the object on which it is called. When cloning is required for objects of a class, the class should override method clone as a public method and should implement interface Cloneable (package java.lang). The default implementation of this method performs a socalled shallow copy instance variable values in one object are copied into another object of the same type. For reference types, only the references are copied. A typical overridden clone method s implementation would perform a deep copy that creates a new object for each reference type instance variable. There are many subtleties to overriding method clone. You can learn more about cloning in the following article: java.sun.com/developer/jdctechtips/2001/tt0306.html 2005 Pearson Education, Inc. All rights reserved.
Η κλάση Object Method Description Equals This method compares two objects for equality and returns true if they are equal and false otherwise. The method takes any Object as an argument. When objects of a particular class must be compared for equality, the class should override method equals to compare the contents of the two objects. The method s implementation should meet the following requirements: It should return false if the argument is null. It should return true if an object is compared to itself, as in object1.equals( object1 ). It should return true only if both object1.equals( object2 ) and object2.equals( object1 ) would return true. For three objects, if object1.equals( object2 ) returns true and object2.equals( object3 ) returns true, then object1.equals( object3 ) should also return true. If equals is called multiple times with the two objects and the objects do not change, the method should consistently return true if the objects are equal and false otherwise. A class that overrides equals should also override hashcode to ensure that equal objects have identical hashcodes. The default equals implementation uses operator == to determine whether two references refer to the same object in memory. Section 29.3.3 demonstrates class String s equals method and differentiates between comparing String objects with == and with equals. 2005 Pearson Education, Inc. All rights reserved.
Η κλάση Object Method Description finalize This protected method (introduced in Section 8.10 and Section 8.11) is called by the garbage collector to perform termination housekeeping on an object just before the garbage collector reclaims the object s memory. It is not guaranteed that the garbage collector will reclaim an object, so it cannot be guaranteed that the object s finalize method will execute. The method must specify an empty parameter list and must return void. The default implementation of this method serves as a placeholder that does nothing. getclass Every object in Java knows its own type at execution time. Method getclass (used in Section 10.5 and Section 21.3) returns an object of class Class (package java.lang) that contains information about the object s type, such as its class name (returned by Class method getname). You can learn more about class Class in the online API documentation at java.sun.com/j2se/5.0/docs/api/java/lang/class.html. 2005 Pearson Education, Inc. All rights reserved.
Η κλάση Object Method hashcode notify, notifyall, wait tostring Description A hashtable is a data structure (discussed in Section 19.10) that relates one object, called the key, to another object, called the value. When initially inserting a value into a hashtable, the key s hashcode method is called. The hashcode value returned is used by the hashtable to determine the location at which to insert the corresponding value. The key s hashcode is also used by the hashtable to locate the key s corresponding value. Methods notify, notifyall and the three overloaded versions of wait are related to multithreading, which is discussed in Chapter 23. In J2SE 5.0, the multithreading model has changed substantially, but these features continue to be supported. This method (introduced in Section 9.4.1) returns a String representation of an object. The default implementation of this method returns the package name and class name of the object s class followed by a hexadecimal representation of the value returned by the object s hashcode method. 2005 Pearson Education, Inc. All rights reserved.
Πολυμορφισμός Ορισμός Webster: pol-y-mor-phism n. : a genetic variation that produces differing characteristics in individuals of the same population or species pol-y-mor-phous adj. : having, assuming, or passing through many or various forms, stages, or the like Η βασική αρχή και στόχοι της γενίκευσης και της αφαίρεσης είναι : Επαναχρησιμοποίηση (Reuse) Διαλειτουργικότητα (Interoperability)
Πολυμορφισμός Πολυμορφισμός Επιτρέπει «programming in the general» Η ίδια κλήση μπορεί να παράγει «πολλούς τύπους» αποτελεσμάτων Interfaces υλοποιούνται από κλάσεις για να εκχωρούν κοινή λειτουργικότητα σε πιθανώς μη σχετιζόμενες κλάσεις
Παράδειγμα Πρόγραμμα προσομοίωσης κίνησης διαφόρων τύπων ζώων για βιολογική μελέτη Υπερκλάση Animal Υποκλάσεις Fish, Frog, Bird H υπερκλάση Animal περιλαμβάνει τη μέθοδο move και διατηρεί την τρέχουσα θέση ενός ζώoυ Κάθε τύπος ζώου αντιδρά με μοναδικό τρόπο στη μέθοδο move Το Fish κολυμπά τρία μέτρα Το Frog πηδάει πέντε πόδια Το Bird πετάει δέκα μέτρα
Πολυμορφισμός Πολυμορφισμός Όταν ένα πρόγραμμα καλεί μία μέθοδο μέσω μιας μεταβλητής υπερκλάσης κατά την εκτέλεση, καλείται η σωστή έκδοση υποκλάσης της μεθόδου, με βάση τον τύπο αναφοράς που αποθηκεύεται στη μεταβλητή υπερκλάσης Το ίδιο μήνυμα (μέθοδος και υπογραφή μεθόδου) στέλνεται σε διαφορετικά αντικείμενα που έχει «πολλές μορφές» αποτελεσμάτων Διευκολύνει την προσθήκη νέων κλάσεων στο σύστημα με ελάχιστες τροποποιήσεις στον κώδικα του συστήματος 2005 Pearson Education, Inc. All rights reserved.
Παρατήρηση Ο πολυμορφισμός επιτρέπει να χειριζόμαστε τις γενικότητες και να αφήνουμε το περιβάλλον εκτέλεσης να χειριστεί τα ειδικά θέματα. Μπορούμε να δίνουμε εντολή στα αντικείμενα ώστε να συμπεριφέρονται με τρόπους κατάλληλους για αυτά τα αντικείμενα, χωρίς να γνωρίζουν τους τύπους των αντικειμένων (εφόσον τα αντικείμενα ανήκουν στην ίδια ιεραρχία κληρονομικότητας). 2005 Pearson Education, Inc. All rights reserved.
Παρατήρηση Ο πολυμορφισμός προωθεί την επεκτασιμότητα: το λογισμικό που καλεί πολυμορφική συμπεριφορά είναι ανεξάρτητο του τύπου αντικειμένου, στο οποίο στέλνονται τα μηνύματα. Σε ένα σύστημα μπορούν να ενσωματωθούν νέοι τύποι αντικειμένων που μπορούν να αποκριθούν σε κλήσεις υπαρχουσών μεθόδων χωρίς να απαιτείται τροποποίηση στο βασικό σύστημα. Μόνο ο κώδικας του πελάτη που δημιουργεί νέα αντικείμενα πρέπει να τροποποιηθεί για τους νέους τύπους. 2005 Pearson Education, Inc. All rights reserved.
Παρουσίαση πολυμορφικής συμπεριφοράς Μία αναφορά υπερκλάσης χρησιμοποιείται σε αντικείμενο υποκλάσης! Αυτό είναι δυνατό γιατί κάθε αντικείμενο της υποκλάσης είναι ένα αντικείμενο της υπερκλάσης ΤΟ ΑΝΤΙΣΤΡΟΦΟ ΔΕΝ ΙΣΧΥΕΙ 2005 Pearson Education, Inc. All rights reserved.
Εκχώρηση αναφορών υπερκλάσης και υποκλάσης σε μεταβλητές υπερκλάσης και υποκλάσης 1 // Fig. 10.1: PolymorphismTest.java 2 // Assigning superclass and subclass references to superclass and 3 // subclass variables. 4 5 public class PolymorphismTest 6 { 7 public static void main( String args[] ) 8 { 9 // εκχωρεί την αναφορά υπερκλάσης στη μεταβλητή υπερκλάσης 10 CommissionEmployee3 commissionemployee = new CommissionEmployee3( 11 "Sue", "Jones", "222-22-2222", 10000,.06 ); 12 13 // εκχωρεί την αναφορά υποκλάσης στη μεταβλητή υποκλάσης 14 BasePlusCommissionEmployee4 basepluscommissionemployee = 15 new BasePlusCommissionEmployee4( 16 "Bob", "Lewis", "333-33-3333", 5000,.04, 300 ); 17 18 // καλεί την tostring στο αντικείμενο υπερκλάσης με μεταβλητή υπερκλάσης 19 System.out.printf( "%s %s:\n\n%s\n\n", 20 "Call CommissionEmployee3's tostring with superclass reference ", 21 "to superclass object", commissionemployee.tostring() ); 22 23 // καλεί την tostring στο αντικείμενο υποκλάσης με μεταβλητή υποκλάσης 24 System.out.printf( "%s %s:\n\n%s\n\n", 25 "Call BasePlusCommissionEmployee4's tostring with subclass", 26 "reference to subclass object", 27 basepluscommissionemployee.tostring() ); 28 Τυπικές εκχωρήσεις αναφορών
29 // invoke tostring on subclass object using superclass variable 30 CommissionEmployee3 commissionemployee2 = 31 basepluscommissionemployee; 32 System.out.printf( "%s %s:\n\n%s\n", 33 "Call BasePlusCommissionEmployee4's tostring with superclass", 34 "reference to subclass object", commissionemployee2.tostring() ); 35 } // end main 36 } // end class PolymorphismTest Call CommissionEmployee3's tostring with superclass reference to superclass object: commission employee: Sue Jones social security number: 222-22-2222 gross sales: 10000.00 commission rate: 0.06 Call BasePlusCommissionEmployee4's tostring with subclass reference to subclass object: base-salaried commission employee: Bob Lewis social security number: 333-33-3333 gross sales: 5000.00 commission rate: 0.04 base salary: 300.00 Call BasePlusCommissionEmployee4's tostring with superclass reference to subclass object: base-salaried commission employee: Bob Lewis social security number: 333-33-3333 gross sales: 5000.00 commission rate: 0.04 base salary: 300.00 Εκχωρεί την αναφορά στο αντικείμενο υποκλάσης basepluscommissionemployee σε μία μεταβλητή υπερκλάσης CommissionEmployee3 Polymorphically call basepluscommissionemployee s tostring method ΠΡΟΣΟΧΗ Όταν μία μεταβλητή υπερκλάσης περιέχει αναφορά σε αντικείμενο υποκλάσης και αυτή η αναφορά χρησιμοποιείται για να καλέσει μία μέθοδο, στην πραγματικότητα καλεί την έκδοση υποκλάσης της μεθόδου
Abstract κλάσεις και μέθοδοι Abstract κλάσεις Κλάσεις οι οποίες είναι πολύ γενικές για να δημιουργήσουν πραγματικά αντικείμενα Χρησιμοποιούνται μόνο ως abstract υπερκλάσεις για τον ορισμό ειδικών (concrete) υποκλάσεων και για τη δήλωση μεταβλητών αναφοράς Πολλές ιεραρχίες κληρονομικότητας έχουν abstract υπερκλάσεις στα υψηλότερα επίπεδα Keyword abstract Χρησιμοποιείται για να δηλώσει μία κλάση abstract Χρησιμοποιείται επίσης για να δηλώσει μία μέθοδο abstract Οι abstract κλάσεις συνήθως περιέχουν abstract μεθόδους Όλες οι ειδικές υποκλάσεις πρέπει να δηλώνουν «τα κομμάτια που λείπουν» παρέχοντας υλοποιήσεις για κάθε μέθοδο που δηλώνουν 2005 Pearson Education, Inc. All rights reserved.
Abstract κλάσεις Μία abstract κλάση δεν μπορεί να γίνει instantiated Χρησιμοποιείται στην ιεραρχία των κλάσεων για να οργανώσει κοινά χαρακτηριστικά σε κατάλληλα επίπεδα Μια abstract μέθοδος δεν έχει υλοποίηση, έχει μόνο όνομα και υπογραφή (signature) Μία abstract κλάση συχνά περιλαμβάνει abstract μεθόδους Οι abstract μέθοδοι μπορούν να εμφανίζονται σε κλάσεις που έχουν οι ίδιες δηλωθεί abstract Ο modifier abstract χρησιμοποιείται να ορίσει abstract κλάσεις & μεθόδους Τα παιδιά μίας abstract κλάσης αναμένεται να ορίσουν υλοποιήσεις των abstract μεθόδων Αν μία child κλάση δεν ορίσει όλες τις abstract μεθόδους του γονέα, τότε το παιδί είναι επίσης abstract
Παράδειγμα Παραγωγή ειδικών κλάσεων Circle, Square, Triangle από την abstract υπερκλάση TwoDimensionalShape Παραγωγή ειδικών κλάσεων Sphere, Cube, Tetrahedron από την abstract υπερκλάση ThreeDimensionalShape Αν η abstract κλάση TwoDimensionalShape λάβει το μήνυμα draw γνωρίζει ότι τα δισδιάστατα σχήματα πρέπει να σχεδιάζονται αλλά δεν γνωρίζει ποιο συγκεκριμένο σχήμα να σχεδιάσει, συνεπώς δεν μπορεί να υλοποιήσει μία πραγματική μέθοδο draw
Παράδειγμα Έστω μία εφαρμογή paint-brush: Θέλουμε να αναπαραστήσουμε το drawing ως συλλογή αντικειμένων, που το καθένα αναπαριστά συγκεκριμένο σχήμα Θέλουμε να αναπαραστήσουμε κάθε τύπο σχήματος με μία κατάλληλη κλάση. Αντικείμενα αυτών των κλάσεων θα ξέρουν πως να ζωγραφίσουν τον εαυτό τους Οι κλάσεις έχουν κοινές ιδιότητες (location, size, color,...) και κοινές συμπεριφορές (moveto(), resize(),...). Θέλουμε να έχουμε μία κοινή υπερκλάση για όλες αυτές τις κλάσεις
Abstract κλάσεις Δεν θα δημιουργήσουμε όμως στιγμιότυπο της κλάσης Figure. Επομένως:
Abstract κλάσεις Επίσης ορίζουμε ως abstract τη μέθοδο draw() γιατί δεν έχει νόημα η υλοποίησή της στην κλάση Figure
Abstract κλάσεις Μία υποκλάση της κλάσης Figure πρέπει είτε να είναι abstract είτε να υλοποιήσει όλες τις abstract μεθόδους της κλάσης Figure Μία abstract μέθοδος δεν μπορεί να οριστεί ως final, γιατί πρέπει να γίνει overridden σε μία child κλάση Μία abstract μέθοδος δεν μπορεί να δηλωθεί ως static, γιατί δεν μπορεί να επικαλεστεί χωρίς υλοποίηση
Παρατήρηση Μία abstract class δηλώνει τα κοινά χαρακτηριστικά και συμπεριφορές (αφαιρετικές και ειδικές) διαφόρων κλάσεων σε μία ιεραρχία κλάσεων. Μία abstract class τυπικά περιέχει μία ή περισσότερες abstract methods που πρέπει να επικαλύψουν οι υποκλάσεις αν πρέπει να είναι ειδικές. Οι μεταβλητές στιγμιότυπου (πεδία) και οι μέθοδοι μιας abstract class υπόκεινται στους συνηθισμένους κανόνες κληρονομικότητας. 2005 Pearson Education, Inc. All rights reserved.
Προγραμματιστικό λάθος Η προσπάθεια δημιουργίας ενός αντικειμένου μίας abstract class αποτελεί λάθος μεταγλώττισης Οι constructors και οι static μέθοδοι δεν μπορούν να δηλωθούν abstract Οι constructors δεν κληρονομούνται, συνεπώς ένας abstract constructor δεν θα μπορούσε να υλοποιηθεί ποτέ. Αν και οι μη private static μέθοδοι μπορούν να κληρονομηθούν, δεν μπορούν να επικαλυφθούν. Αφού οι abstract μέθοδοι δημιουργούνται για να επικαλυφθούν, δεν θα είχε νόημα να δηλώσουμε μία static μέθοδο ως abstract Αποτελεί λάθος μεταγλώττισης αν δεν υλοποιήσετε τις abstract μεθόδους μιας υπερκλάσης σε μία υποκλάση εκτός και αν η υποκλάση δηλωθεί επίσης abstract 2005 Pearson Education, Inc. All rights reserved.
final μέθοδοι και κλάσεις final methods Δεν μπορούν να επικαλυφθούν Οι private και static μέθοδοι είναι έμμεσα final Οι final μέθοδοι αναλύονται κατά τη μεταγλώττιση, αυτό είναι γνωστό ως στατική σύνδεση final classes Δεν μπορούν να επεκταθούν από μία υποκλάση Όλες οι μέθοδοι σε μία final class είναι έμμεσα final
Προγραμματιστικό λάθος Η προσπάθεια δήλωσης υποκλάσης μιας final class αποτελεί λάθος μεταγλώττισης 2005 Pearson Education, Inc. All rights reserved.
Παρατήρηση Στο Java API, η μεγάλη πλειονότητα των κλάσεων δεν δηλώνονται ως final. Αυτό επιτρέπει την κληρονομικότητα και τον πολυμορφισμό. Ωστόσο σε μερικές περιπτώσεις, είναι σημαντικό να δηλώνετε τις κλάσεις ως final γενικά για λόγους ασφαλείας.
Παραδείγματα Τι συμβαίνει κατά τη μετάφραση του παρακάτω προγράμματος Java: final class A {...} class B extends A {... } Compile error: We can t extend final classes
Παραδείγματα Shape είναι μια αφηρημένη (abstract) κλάση που ορίζεται ως ακολούθως: abstract class Shape { abstract void draw(); abstract void move(int x, int y); abstract void scale(double factor); int x,y; int width, height; } Τι συμβαίνει κατά τη μετάφραση της παρακάτω ειδικής κλάσης Square που εξειδικεύει την Shape? class Square extends Shape { void move(int x, int y) {this.x = x; this.y = y;}; } Compile error: Concrete classes extending an abstract class should implement all its abstract methods
Πηγές/Acknowledgements http://java.sun.com/j2se H. M. Deitel, P. J. Deitel, Java Προγραμματισμός, 6η έκδοση, Μ. Γκιούρδας, 2006 D. Barnes, M. Kolling, Αντικειμενοστρεφής Προγραμματισμός σε Java, Κλειδάριθμος, 2008 Βασίλης Χριστοφίδης, Αντικειμενοστρεφής Προγραμματισμός, Πανεπιστήμιο Κρήτης Κ. Τσαγκάρης, Εισαγωγή στις εφαρμογές της Java, Πανεπιστήμιο Πειραιώς Jones, Evan, Adam Marcus, and Eugene Wu. 6.092 Introduction to Programming in Java,January IAP 2010. (Massachusetts Institute of Technology: MIT OpenCourseWare), http://ocw.mit.edu (Accessed 10 Mar, 2013). License: Creative Commons BY-NC-SA