Προγραµµατισµός ΙΙ Ηγλώσσααντικειµενοστραφούς προγραµµατισµού Java ιδάσκων ηµήτριος Κατσαρός, Ph.D. @ Τµ. Μηχανικών Η/Υ, Τηλεπικοινωνιών & ικτύων Πανεπιστήµιο Θεσσαλίας ιάλεξη 8η: 10/05/2006 & 11/05/2006 1
ιεπαφές και Εσωτερικές κλάσεις Interfaces and Inner Classes 2
ιεπαφές - Interfaces Μια διεπαφή (interface) είναι κάτι ανάλογο µιας ακραίας περίπτωσης αφηρηµένης κλάσης Όµως, ένα interface δεν είναι κλάση Είναι ένας τύπος δεδοµένων που µπορεί να ικανοποιηθεί από οποιαδήποτε κλάση υλοποιεί αυτό το interface Ησύνταξηγιαναορίσουµε έναinterface είναι παρόµοια µεαυτήορισµού µιας κλάσης Εκτός από τη λέξη interface που χρησιµοποιείται αντί της λέξης class Ένα interface καθορίζει ένα σύνολο µεθόδων που κάθε κλάση, ηοποίαυλοποιείτοinterface, πρέπει να έχει Περιέχει µόνο κεφαλίδες µεθόδων και δηλώσεις σταθερών εν έχει instance variables ούτε πλήρεις ορισµούς µεθόδων 3
ιεπαφές - Interfaces Ένα interface λειτουργεί παρόµοια µε µια base class, όµως δεν είναι base class Μερικέςγλώσσεςεπιτρέπουνµια κλάση να παράγεται από περισσότερες από µια διαφορετικές base classes Αυτή η πολλαπλή κληρονοµικότητα (multiple inheritance) δεν επιτρέπεται στη Java Αντί γι αυτό, η Java προσεγγίζει την πολλαπλή κληρονοµικότητα µε ταinterfaces 4
ιεπαφές - Interfaces Ένα interface και όλες οι κεφαλίδες των µεθόδων του θα πρέπει να δηλώνονται public εν µπορεί να δηλωθούν private, protected, ή µε package προσπέλαση Όταν µια κλάση υλοποιεί ένα interface, πρέπει να κάνει όλες τις µεθόδους του interface public Επειδή ένα interface είναι ένας τύπος δεδοµένων, µια µέθοδος µπορεί να δέχεται ως όρισµαέναντύποinterface Αυτή η παράµετρος θα δέχεται ως όρισµα οποιαδήποτε κλάση υλοποιεί το interface 5
ΗδιεπαφήOrdered 6
ιεπαφές Για να υλοποιήσουµε έναinterface, µια κλάση πρέπει να κάνει δυο πράγµατα: 1. Να περιλάβει τη φράση implements Interface_Name Στην αρχή του ορισµού της Εάν υλοποιεί περισσότερα από ένα interface, κάθε ένα από αυτά παρατίθεται, χωρισµένα µεκόµµα 2. Η κλάση πρέπει να υλοποιήσει όλες τις κεφαλίδες µεθόδων που υπάρχουν στους ορισµούς των interface(s) Σηµειώστε τη χρήση του Object ως τύπο παραµέτρου στα επόµενα παραδείγµατα 7
Υλοποίηση µιας ιεπαφής 8
Υλοποίηση µιας ιεπαφής 9
Αφηρηµένες κλάσεις που υλοποιούν Interface Οι αφηρηµένες κλάσεις µπορεί να υλοποιούν ένα ή περισσότερα interfaces Κάθε κεφαλίδα µεθόδου που δίνεται σε ένα interface αλλά δεν υλοποιείται στην κλάση, σηµατοδοτεί µια αφηρηµένη µέθοδο Μια (concrete) κλάσηπρέπειναέχειορισµούς για όλες τις κεφαλίδες µεθόδων που δίνονται στην αφηρηµένη κλάση, από όπου παράγεται, και ορισµούςγιαόλεςτιςκεφαλίδεςµεθόδων των interfaces που υλοποιεί 10
Αφηρηµένη κλάση που υλοποιεί Interface 11
Παραγόµενες ιεπαφές (Derived Interfaces) Όπως και οι κλάσεις, ένα interface µπορεί να παραχθεί από ένα base interface Αυτό αποκαλείται επέκταση (extending) του interface Το παραγόµενο interface πρέπει να περιλαµβάνει τη φράση extends BaseInterfaceName Μια (concrete) κλάση που υλοποιεί ένα παραγόµενο interface πρέπει να έχει ορισµούς για κάθε µέθοδο του παραγόµενου interface καθώςεπίσηςκαιγιακάθεµέθοδο του base interface 12
Extending ένα Interface 13
Παγίδα: Ησηµασιολογία µιας ιεπαφής δεν επιβάλλεται Όταν µια κλάση υλοποιεί ένα interface, ο compiler και το run-time σύστηµαελέγχουντησύνταξητου interface και την υλοποίησή του Όµως, δεν ελέγχουν εάν το σώµα τουinterface είναι συνεπές µε το προοριζόµενο νόηµα Η απαιτούµενη σηµασιολογία για το interface κανονικά ενσωµατώνονται στην τεκµηρίωση του interface Έτσι, γίνεται αρµοδιότητα του προγραµµατιστή που υλοποιεί το interface, να ακολουθήσει τη σηµασιολογία Εάν το σώµατηςµεθόδου δεν ικανοποιεί την προκαθορισµένη σηµασιολογία, τότε το λογισµικό που γράφεται για τις κλάσεις που υλοποιούν το interface ίσως να µην λειτουργεί κανονικά 14
Το interface Comparable Είναι εύκολο να επινοήσουµε/αναζητήσουµε έναν αλγόριθµο (π.χ., Selection Sort) για να ταξινοµήσουµε ένανµερικώς πλήρη πίνακα από double σε αύξουσα διάταξη Προφανώς, αυτός ο κώδικας µπορεί να µετασχηµατιστεί ώστε να ταξινοµεί σε φθίνουσα διάταξη, ήναταξινοµεί String Όλες αυτές οι µέθοδοι θα είναι ουσιαστικά παρόµοιες, αλλά κάθε απαιτούµενη µικρο-αλλαγή θα ήταν ενόχληση Οι µοναδικές διαφορές θα ήταν οι τύποι δεδοµένων και η διάταξη ταξινόµησης Χρησιµοποιώντας το interface Comparable θα µπορούσαµε ναέχουµε µια µόνο µέθοδο ταξινόµησης που καλύπτει όλες τις περιπτώσεις 15
Το interface Comparable Το interface Comparable βρίσκεται στο package java.lang, και έτσι δεν χρειάζεται δήλωση import Έχει µόνο την ακόλουθη κεφαλίδα µεθόδου που πρέπει να υλοποιηθεί: public int compareto(object other); Είναι ευθύνη του προγραµµατιστή να ακολουθήσει τη σηµασιολογία του interface Comparable όταν το υλοποιεί 16
Ησηµασιολογία της διεπαφής Comparable Η µέθοδος compareto πρέπει να επιστρέφει Έναν αρνητικό αριθµό, εάντοκαλούναντικείµενο προηγείται" της παραµέτρου other Μηδέν, εάν το το καλούν αντικείµενο ισούται µετην παράµετρο other Ένα θετικό αριθµό, εάν το καλούν αντικείµενο έπεται της παραµέτρου other Εάν η παράµετρος other δεν είναι ίδιου τύπου όπως η κλάση που ορίζουµε, τότε θα πεταχτεί µια εξαίρεση ClassCastException 17
Ησηµασιολογία της διεπαφής Comparable Σχεδόν οποιαδήποτε έννοια του προηγείται είναι αποδεκτή Ειδικότερα, όλες οι standard less-than σχέσεις πάνω σε αριθµούς και η λεξικογραφική διάταξη σε strings είναι κατάλληλες Ησχέση έπεται" είναι απλά το αντίστροφο της προηγείται 18
Ησηµασιολογία της διεπαφής Comparable Και άλλες διατάξεις µπορεί να εξεταστούν, εφόσον επιβάλλουν πλήρη διάταξη (total ordering) Μια τέτοια διάταξη πρέπει να ικανοποιεί τους ακόλουθους κανόνες: (Irreflexivity) Για κανένα αντικείµενο o, το o δεν προηγείται του o (Trichotomy) Για δυο οποιαδήποτε αντικείµενα o1 και o2, ένα και µόνο ένα από τα ακόλουθα ισχύει: το o1 προηγείται του o2, το o1 έπεται του o2, ήτοo1 ισούται µετοo2 (Transitivity) Εάν το o1 προηγείται του o2 και το o2 προηγείται του o3, τότε το o1 προηγείται του o3 Το ισούται της σηµασιολογίας της µεθόδου compareto πρέπει να συµπίπτει µε τηνµέθοδο equals εάν είναι δυνατό, αλλά αυτό δεν είναι εντελώς ζητούµενο 19
Χρήση της διεπαφής Comparable Το επόµενο παράδειγµαχρησιµοποιεί τον απλό αλγόριθµο SelectionSort Ηνέαέκδοση, GeneralizedSelectionSort, περιλαµβάνει µια µέθοδο που µπορεί να ταξινοµήσει οποιοδήποτε µερικώς πλήρη πίνακα, τουοποίουο base τύπος υλοποιεί το interface Comparable Περιέχει και κατάλληλες µεθόδους indexofsmallest και interchange Σηµείωση: Οι κλάσεις Double και String υλοποιούν το interface Comparable Τα interfaces εφαρµόζονται µόνο σε κλάσεις Ένας primitive τύπος (π.χ., double) δεν µπορεί να υλοποιεί ένα interface 20
Κλάση GeneralizedSelectionSort: Μέθοδος sort 21
Κλάση GeneralizedSelectionSort: Μέθοδος sort 22
Κλάση GeneralizedSelectionSort: Μέθοδος sort 23
Ταξινόµηση πινάκων τύπου Comparable 24
Ταξινόµηση πινάκων τύπου Comparable 25
Ταξινόµηση πινάκων τύπου Comparable 26
Ορισµένες σταθερές σε interfaces Ένα interface µπορεί να περιέχει και ορισµένες constants, πέρα από τις κεφαλίδες µεθόδων Όποιες µεταβλητές ορίζονται σε ένα interface πρέπει να είναι public, static, και final Επειδή αυτό είναι η µόνη επιλογή, η Java επιτρέπει να παραλείπουµε αυτούς τους modifiers Κάθε κλάση που υλοποιεί το interface έχει πρόσβαση σε αυτές τις defined constants 27
Παγίδα: Ασυνεπή interfaces Στη Java, κάθε κλάση µπορεί να έχει µια µόνο base κλάση Αυτό αποτρέπει ασυνέπειες που µπορεί να προκύψουν από διαφορετικούς ορισµούς µεθόδων που έχουν την ίδια κεφαλίδα Επιπρόσθετα, µια κλάση µπορεί να υλοποιεί οποιοδήποτε αριθµόαπόinterfaces Αφού τα interfaces δεν έχουν σώµατα µεθόδων, το παραπάνω πρόβληµα δενµπορεί να προκύψει Όµως, υπάρχουν άλλα είδη ασυνεπειών που µπορεί να προκύψουν 28
Παγίδα: Ασυνεπή interfaces Όταν µια κλάση υλοποιεί δυο interfaces: Ένας τύπος ασυνέπειας θα προκύψει, εάν τα interfaces έχουν constants µε τοίδιοόνοµα, αλλά µεδιαφορετικέςτιµές Ένας άλλος τύπος ασυνέπειας θα προκύψει, εάν τα interfaces περιέχουν µεθόδους µε τοίδιοόνοµα αλλά µε διαφορετικούς επιστρεφόµενους τύπους Εάν ο ορισµός της κλάσης υλοποιεί δυο ασυνεπή interfaces, τότε αυτό είναι error, και ο ορισµός τηςκλάσηςείναιµηέγκυρος 29
To interface Serializable Ένα ακραίο, αλλά κοινά χρησιµοποιούµενο παράδειγµα interface είναι το interface Serializable εν έχει κεφαλίδες µεθόδων ούτε και defined constants: Είναι εντελώς κενό Χρησιµοποιείται απλά ως ετικέτα τύπου που σηµατοδοτεί στο σύστηµα ότιµπορεί να υλοποιήσει I/O αρχείων µε ένανσυγκεκριµένο τρόπο 30
To interface Cloneable Το interface Cloneable είναι ακόµη έναµη συνηθισµένο παράδειγµαενόςjava interface εν περιέχει κεφαλίδες µεθόδων ούτε defined constants Χρησιµοποιείται για να δηλώσει πώς η µέθοδος clone (κληρονοµούµενη από την κλάση Object) θα πρέπει να χρησιµοποιηθεί και να ξανα-οριστεί 31
To interface Cloneable Η µέθοδος Object.clone() εκτελεί µια bitby-bit αντιγραφή των δεδοµένων του αντικειµένου στον αποθηκευτικό χώρο Εάν τα δεδοµένα είναι όλα primitive τύπου ή δεδοµένα από immutable τύπους κλάσεων (όπως η κλάση String), τότε αυτή είναι αρκετή Αυτή είναι η απλούστερη περίπτωση Το επόµενο είναι ένα παράδειγµα µιας απλής κλάσης που δεν έχει instance variables τύπου mutable κλάσης, και δεν έχει καθορισµένη base κλάση Έτσι, η base κλάση είναι η Object 32
Υλοποίηση της clone: Απλή περίπτωση 33
To interface Cloneable Εάν τα δεδοµένα του αντικειµένου, που πρόκειται να αντιγραφεί µε τηνclone, περιλαµβάνουν instance variables τωνοποίωνοτύποςείναιµια mutable κλάση, τότε η απλή υλοποίηση της clone θα προκαλούσε ένα κενό ασφάλειας (privacy leak) Όταν υλοποιούµε τοinterface Cloneable για µια κλάση όπως αυτή που αναφέραµε: Πρώτα ενεργοποιούµετηµέθοδο clone της βασικής κλάσης Object (ή οποιασδήποτε βασικής κλάσης από την οποία παράγεται η εξεταζόµενη κλάση) Κατόπιν, κάνουµε reset τις τιµές των νέων instance variables των οποίων οι τύποι είναι mutable κλάσεις Αυτό γίνεται µετονακάνουµεαντίγραφατωνinstance variables µε ενεργοποίηση των δικών τους µεθόδων clone 34
To interface Cloneable Να σηµειωθεί ότι αυτό θα δουλέψει κανονικά µόνο εάν το interface Cloneable υλοποιείται ορθάγιατιςκλάσειςστιςοποίεςανήκουνοι instance variables Και για τις κλάσεις οι οποίες περιλαµβάνονται στις κλάσεις των instance variables, κ.ο.κ. Το επόµενο δείχνει ένα παράδειγµα 35
Υλοποίηση της clone: ύσκολη περίπτωση 36
Απλές χρήσεις των Εσωτερικών Κλάσεων (Inner Classes) Οι Inner κλάσεις είναι κλάσεις που ορίζονται µέσα σε άλλες κλάσεις Η κλάση που περιλαµβάνει την inner κλάση αποκαλείται outer κλάση εν υπάρχει συγκεκριµένηθέσηστηνouter κλάση, όπου θα πρέπει να τοποθετηθεί ο ορισµός της inner κλάσης (ήτωνκλάσεων) Τοποθετώντας τον στην αρχή ή στο τέλος, σηµαίνει ότι θα τον εντοπίζουµε εύκολα 37
Απλές χρήσεις των Inner κλάσεων Οορισµός µιας inner κλάσεις είναι ένα µέλος της outer κλάσης µε τον ίδιο τρόπο που οι instance variables και οι µέθοδοι της outer class είναι µέλη της Μια inner κλάση είναι τοπική (local) στον ορισµό της outer κλάσης Το όνοµα µιας inner κλάσης µπορεί να χρησιµοποιηθεί οπουδήποτε εκτός του ορισµού της outer κλάσης Εάν η inner κλάση είναι ιδιωτική, τότε η inner κλάση δεν µπορεί να προσπελαστεί by name εκτός του ορισµού της outer κλάσης 38
Απλές χρήσεις των Inner κλάσεων Οι inner κλάσεις έχουν δυο κύρια πλεονεκτήµατα Καθιστούν τις outer κλάσεις περισσότερο αυτόπεριεχόµενες Οι µέθοδοί τους έχουν πρόσβαση στις ιδιωτικές µεθόδους και στις instance variables της άλλης κλάσης Χρησιµοποιώντας µια inner κλάση ως βοηθητική κλάση είναι µια από τις πιο χρήσιµες εφαρµογές των inner κλάσεων Εάν χρησιµοποιηθεί ως βοηθητική κλάση, η inner κλάση θα πρέπει να καθορίζεται ως private 39
Υπόδειξη: Οι Inner και Outer κλάσεις έχουν πρόσβαση η µια στα ιδιωτικά µέλη της άλλης Μέσα στον ορισµό µιας µεθόδου µιας inner κλάσης: Είναι έγκυρο να αναφερόµαστε σε µια private instance variable της outer κλάσης Είναι έγκυρο να ενεργοποιούµε µια private µέθοδο της outer κλάσης Μέσα στον ορισµό µιας µεθόδου µιας outer κλάσης Είναι έγκυρο να αναφερόµαστε σε µια private instance variable της inner κλάσης για ένα αντικείµενο της inner κλάσης Είναι έγκυρο να ενεργοποιούµε µια (nonstatic) µέθοδο της inner κλάσης, εφόσον κάποιο αντικείµενο της inner κλάσης χρησιµοποιείται ως καλούν αντικείµενο Μέσα στον ορισµό των inner ή outer κλάσεων, οι modifiers public και private είναι ισοδύναµοι 40
Κλάση που περιέχει Inner κλάση 41
Κλάση που περιέχει Inner κλάση 42
Κλάση που περιέχει Inner κλάση 43
Το αρχείο.class για µια Inner κλάση Μεταγλωττίζοντας µια οποιαδήποτε κλάση στη Java παράγει ένα αρχείο.class µεόνοµα ClassName.class Μεταγλωττίζοντας µια κλάση µε µια (ή περισσότερες) inner κλάσεις προκαλεί τη µεταγλώττιση και των δυο (ήόλων) των κλάσεων, και παράγει δυο (ή περισσότερα) αρχεία.class Όπως ClassName.class και ClassName$InnerClassName.class 44
Static Inner κλάσεις Μια κανονική inner κλάση έχει µια σχέση µεταξύ των αντικειµένων της και του αντικειµένου της outer κλάσης που δηµιούργησε το αντικείµενο της inner κλάσης Αυτό επιτρέπει τον ορισµό τηςinner κλάσης να αναφέρεται σε µια instance variable, ήνα ενεργοποιεί µια µέθοδο της outer κλάσης Υπάρχουν µερικές καταστάσεις όµως, όπου µια inner κλάση πρέπει να είναι static Εάν ένα αντικείµενο της inner κλάσης δηµιουργείται µέσα σε µια static µέθοδο της outer κλάσης Εάν η inner κλάση πρέπει να έχει static µέλη 45
Static Inner κλάσεις Αφού µια static inner κλάση δεν έχει σχέση µε ένα αντικείµενο της outer κλάσης, τότε µέσα σε µια µέθοδο της inner κλάσης Οι instance variables της outer κλάσης δεν µπορούν να προσπελαστούν Οι nonstatic µέθοδοι της outer κλάσης δεν µπορούν να ενεργοποιηθούν Γιαναενεργοποιήσουµε µια static µέθοδο ή για να ονοµατίσουµε µια static µεταβλητή µιας static inner κλάσης µέσα σε µια outer κλάση, βάζουµε ωςπρόθεµάτουςτοόνοµατηςinner κλάσης και µια dot 46
Public Inner κλάσεις Εάν η inner κλάση είναι public, τότε µπορεί να χρησιµοποιηθεί εκτός της outer κλάσης Στην περίπτωση της nonstatic inner κλάσης, πρέπει να δηµιουργηθεί χρησιµοποιώντας ένα αντικείµενο της outer κλάσης BankAccount account = new BankAccount(); BankAccount.Money amount = account.new Money("41.99"); Σηµειώστε ότι το πρόθεµα account. πρέπει να προηγείται του new Το νέο αντικείµενο amount µπορεί τώρα να ενεργοποιήσει µεθόδους της inner κλάσης, αλλά µόνο µέσα από την inner κλάση 47
Public Inner κλάσεις Στην περίπτωση µιας static inner κλάσης, η διαδικασία είναι παρόµοια µε, αλλά απλούστερη, µε εκείνη για τις nonstatic inner κλάσεις OuterClass.InnerClass innerobject = new OuterClass.InnerClass(); Σηµειώστε ότι όλες οι επόµενες δηλώσεις είναι αποδεκτές innerobject.nonstaticmethod(); innerobject.staticmethod(); OuterClass.InnerClass.staticMethod(); 48
Υπόδειξη: Αναφορά σε µέθοδο της outer κλάσης Εάν µια µέθοδος ενεργοποιηθεί σε µια inner κλάση Εάν η inner κλάση δεν έχει τέτοια µέθοδο, τότε υπονοείται ενεργοποίηση της µεθόδου µετοίδιο όνοµατηςouter κλάσης Εάν και οι δυο κλάσεις, inner και outer, έχουν µια µέθοδο µεαυτότοόνοµα, τότε υπονοείται ενεργοποίηση της µεθόδου της inner κλάσης Εάν και οι δυο κλάσεις, inner και outer, έχουν µια µέθοδο µεαυτότοόνοµα, και η πρόθεσή µας είναι να ενεργοποιήσουµε τηµέθοδο της outer κλάσης, τότε πρέπει να χρησιµοποιήσουµε τον ακόλουθο τρόπο: OuterClassName.this.methodName() 49
Φωλιάζοντας Inner κλάσεις Είναι έγκυρο να φωλιάζουµε inner κλάσεις µέσα σε inner κλάσεις Οι κανόνες είναι οι ίδιοι όπως πριν, αλλά τα ονόµατα γίνονται µεγαλύτερα εδοµένης µιας κλάσης A, η οποία έχει µια public inner κλάση B, η οποία έχει µια public inner κλάση C, τότε το επόµενο είναι έγκυρο: A aobject = new A(); A.B bobject = aobject.new B(); A.B.C cobject = bobject.new C(); 50
Inner κλάσεις και κληρονοµικότητα εδοµένης µιας OuterClass ηοποίαέχειµια InnerClass Οποιαδήποτε DerivedClass της OuterClass θα έχει αυτόµατα την InnerClass ως inner κλάση Στην περίπτωση αυτή, η DerivedClass δεν µπορεί να κάνει override την InnerClass Μια outer κλάση µπορεί να είναι µια παραγόµενη κλάση Μια inner κλάση µπορεί επίσης να είναι µια παραγόµενη κλάση 51
Ανώνυµες κλάσεις Εάν πρόκειται να δηµιουργηθεί ένα αντικείµενο, αλλά δεν υπάρχει ανάγκη να ονοµατίσουµε τηνκλάσητου αντικειµένου, τότε µπορεί να χρησιµοποιηθεί ο ορισµός µιας ανώνυµης κλάσης (anonymous class) Οορισµός της κλάσης ενσωµατώνεται µέσα στην έκφραση µετον τελεστή new Οι ανώνυµες κλάσεις µερικές φορές χρησιµοποιούνται όταν πρόκειται να ανατεθούν σε µια µεταβλητή άλλου τύπου Ο άλλος τύπος πρέπει να είναι τέτοιος, ώστε το αντικείµενο της ανώνυµης κλάσης να είναι επίσης τύπου ίδιου µεαυτότης µεταβλητής όπου ανατίθεται Ο άλλος τύπος είναι συνήθως ένα Java interface 52
Ανώνυµες κλάσεις 53
Ανώνυµες κλάσεις 54
Ανώνυµες κλάσεις 55