Περίγραμμα Κληρονομικότητα Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia 1 2 Επαναχρησιμοποίηση Κλάσεων Σύνθεση (compositio): σε μια κλάση εντάσσουμε ως στοιχεία χειριστήρια άλλων κλάσεων. Maibox Message Queue Κληρονομικότητα (iheritace): επεκτείνουμε υπάρχουσες κλάσεις, είτε προσθέτοντάς τους καινούρια στοιχεία, είτε αλλάζοντας την λειτουργικότητα μεθόδων τους. Σύνθεση cass WaterSource { private Strig s; WaterSource() { System.out.prit("WaterSource()"); s = ew Strig("Costructed"); pubic Strig tostrig() { retur s; 3 Η χρήση του tostrig(): όταν θέλουμε να μπορεί να γίνει μετατροπή ενός αντικειμένου μιας κλάσης σε συμβολοσειρά, δεν έχουμε παρά να ορίσουμε στην κλάση μια μέθοδο με όνομα tostrig(). 4 Σύνθεση (παράδειγμα) pubic cass SprikerSystem { private Strig vave1, vave2; WaterSource source; foat f; void prit() { System.out.prit("vave1 =" + vave1); System.out.prit("vave2 =" + vave2); System.out.prit("f = " +f); System.out.prit("source =" + source); pubic static void mai (Strig[] args) { SprikerSystem x = ew SprikerSystem(); x.prit(); Περίγραμμα 5 Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia 6
Itroductio to Iheritace Itroductio to Iheritace Iheritace is oe of the mai techiques of object-orieted programmig (OOP) Usig this techique, a very geera form of a cass is first defied ad compied, ad the more speciaized versios of the cass are defied by addig istace variabes ad methods The speciaized casses are said to iherit the methods ad istace variabes of the geera cass Iheritace is the process by which a ew cass is created from aother cass The ew cass is caed a derived cass The origia cass is caed the base cass A derived cass automaticay has a the istace variabes ad methods that the base cass has, ad it ca have additioa methods ad/or istace variabes as we Iheritace is especiay advatageous because it aows code to be reused, without havig to copy it ito the defiitios of the derived casses 7 Copyright 2017 Pearso Ltd. A rights reserved. 8 Derived Casses Derived Casses Whe desigig certai casses, there is ofte a atura hierarchy for groupig them I a record-keepig program for the empoyees of a compay, there are houry empoyees ad saaried empoyees Houry empoyees ca be divided ito fu time ad part time workers Saaried empoyees ca be divided ito those o techica staff, ad those o the executive staff A empoyees share certai characteristics i commo A empoyees have a ame ad a hire date The methods for settig ad chagig ames ad hire dates woud be the same for a empoyees Some empoyees have speciaized characteristics Houry empoyees are paid a houry wage, whie saaried empoyees are paid a fixed wage The methods for cacuatig wages for these two differet groups woud be differet Copyright 2017 Pearso Ltd. A rights reserved. 9 Copyright 2017 Pearso Ltd. A rights reserved. 10 Derived Casses Withi Java, a cass caed Empoyee ca be defied that icudes a empoyees This cass ca the be used to defie casses for houry empoyees ad saaried empoyees I tur, the HouryEmpoyee cass ca be used to defie a PartTimeHouryEmpoyee cass, ad so forth A Cass Hierarchy Copyright 2017 Pearso Ltd. A rights reserved. 11 Copyright 2017 Pearso Ltd. A rights reserved. 12
Derived Casses Sice a houry empoyee is a empoyee, it is defied as a derived cass of the cass Empoyee A derived cass is defied by addig istace variabes ad methods to a existig cass (κλάση κληρονόμος) The existig cass that the derived cass is buit upo is caed the base cass (κλάση βάσης ή κλάση κληροδότης) The phrase exteds BaseCass must be added to the derived cass defiitio: pubic cass HouryEmpoyee exteds Empoyee Derived Casses Whe a derived cass is defied, it is said to iherit (κληρονομεί) the istace variabes ad methods of the base cass that it exteds Cass Empoyee defies the istace variabes ame ad hiredate i its cass defiitio Cass HouryEmpoyee aso has these istace variabes, but they are ot specified i its cass defiitio Cass HouryEmpoyee has additioa istace variabes wagerate ad hours that are specified i its cass defiitio Copyright 2017 Pearso Ltd. A rights reserved. 13 Copyright 2017 Pearso Ltd. A rights reserved. 14 Derived Casses Derived Cass (Subcass) Just as it iherits the istace variabes of the cass Empoyee, the cass HouryEmpoyee iherits a of its methods as we The cass HouryEmpoyee iherits the methods getname, gethiredate, setname, ad sethiredate from the cass Empoyee Ay object of the cass HouryEmpoyee ca ivoke oe of these methods, just ike ay other method A derived cass, aso caed a subcass (υποκλάση), is defied by startig with aother aready defied cass, caed a base cass (κλάση βάσης) or supercass (υπερκλάση), ad addig (ad/or chagig) methods, istace variabes, ad static variabes The derived cass iherits: a the pubic methods a the pubic ad private istace variabes, ad a the pubic ad private static variabes from the base cass The derived cass ca add more istace variabes, static variabes, ad/or methods Copyright 2017 Pearso Ltd. A rights reserved. 15 Copyright 2017 Pearso Ltd. A rights reserved. 16 Iherited Members A derived cass automaticay has a the istace variabes, a the static variabes, ad a the pubic methods of the base cass Members from the base cass are said to be iherited Defiitios for the iherited variabes ad methods do ot appear i the derived cass The code is reused without havig to expicity copy it, uess the creator of the derived cass redefies oe or more of the base cass methods Paret ad Chid Casses A base cass is ofte caed the paret cass A derived cass is the caed a chid cass These reatioships are ofte exteded such that a cass that is a paret of a paret... of aother cass is caed a acestor cass If cass A is a acestor of cass B, the cass B ca be caed a descedet of cass A Copyright 2017 Pearso Ltd. A rights reserved. 17 Copyright 2017 Pearso Ltd. A rights reserved. 18
Περίγραμμα Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Empoyee getname sethiredate ame hiredate setname getname setname Exampe of iheritace Iheritace ad object costructio gethiredate gethiredate Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia getname sethiredate ame hiredate setname HouryEmpoyee gethiredate sethiredate 19 Μ. Δικαιάκος, EΠΛ233 20 Κληρονομικότητα (iheritace) - σύνοψη Κληρονομικότητα (iheritace) - σύνοψη Ορολογία: Base cass: βάση, κληροδότης, ή supercass, υπερκλάση, κλάσηγονέας / πρόγονος. Derived cass: Κλάση-κληρονόμος ή subcass, υποκλάση, κλάσηπαιδί, απόγονος. Απεικόνιση: Όλες οι κλάσεις της Java κληρονομούν από μια γενική κλάση-κληροδότη, την Object. Υπάρχει επίσης η δυνατότητα να ορίζουμε κλάσεις ως κληρονόμους άλλων κλάσεων, πιο εξειδικευμένων από την Object. Η κληρονομικότητα μιας κλάσης από κάποια κλάσηκληροδότη καθορίζεται με χρήση της λέξης-κλειδί exteds. Π.χ.: pubic cass Deterget exteds Ceaser Στην περίπτωση αυτή η νέα κλάση (Deterget) αυτομάτως «κληρονομεί» όλα τα δημόσια και τα φιλικά στοιχεία (πεδία δεδομένων και μέθοδοι ) της βάσης της (Ceaser). 21 22 Περίγραμμα Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia 23 Παράδειγμα Κληρονομικότητας cass Ceaser { private Strig s = "Ceaser"; pubic void apped(strig a) { s += a; pubic void diute() { apped("diute()"); pubic void appy() { apped(" appy()"); pubic void scrub() { apped(" scrub()"); pubic void prit() { System.out.prit(s); pubic static void mai (Strig[] args) { Ceaser x = ew Ceaser(); x.diute(); x.appy(); x.scrub(); x.prit(); 24
Παράδειγμα Κληρονομικότητας (συνέχεια) pubic cass Deterget exteds Ceaser{ pubic void scrub() { apped(" Deterget.scrub()"); super.scrub();//ca base-cass // Add methods to the iterface: pubic void foam() { apped(" foam()"); pubic static void mai(strig[] args) { Deterget x = ew Deterget(); x.diute(); x.appy(); x.scrub(); x.foam(); x.prit(); Ceaser.mai(args); 25 Παράδειγμα Κληρονομικότητας (συνέχεια) Η κλάση Ceaser έχει ορισμένες μεθόδους στην διαπροσωπεία της (iterface): apped(), diute(), appy(), scrub(), prit(). Η Deterget, επειδή προκύπτει από την Ceaser (μέσω κληρονομικότητας), υιοθετεί αυτόματα όλες αυτές τις μεθόδους στην διαπροσωπεία της : η κληρονομικότητα συνεπάγεται την επαναχρησιμοποίηση της διαπροσωπείας. Η κλάση-κληρονόμος μπορεί να τροποποιήσει την λειτουργικότητα μιας μεθόδου της κλάσης-κληροδότη, καλώντας ταυτόχρονα την αναλλοίωτη μέθοδο της κλάσης κληροδότη (με χρήση της λέξης-κλειδί super, η οποία παραπέμπει στην υπερκλάση-κληροδότη). Επιπλέον, η κλάση-κληρονόμος μπορεί να επεκτείνει την διαπροσωπεία της κλάσης-κληροδότη με πρόσθεση νέων μεθόδων. 26 Περίγραμμα Αρχικοποιήσεις και Κληρονομικότητα Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia Η κλάση-κληρονόμου έχει την ίδια διαπροσωπεία (iterface) με την υπερκλάση της, επεκτεινόμενη ίσως με κάποιες καινούριες μεθόδους και πιθανώς με τροποποιημένες κάποιες από τις κληρονομημένες μεθόδους. Τι περιέχει το αντικείμενο που δημιουργείται σύμφωνα με μια κλάση-κληρονόμο; Ένα υποαντικείμενο (subobject) της κλάσης-κληροδότη. Το υποαντικείμενο αυτό είναι το ίδιο σαν να είχε δημιουργηθεί ανεξάρτητα από την κλάση-κληροδότη και όχι εμμέσως από την κλάση-κληρονόμο. Ωστόσο το υποαντικείμενο αυτό είναι περιτυλιγμένο (wrapped) στο αντικείμενο της κλάσης-κληρονόμου. Χρειάζεται προσοχή στην αρχικοποίηση του υποαντικειμένου. 27 28 Αρχικοποιήσεις και Κληρονομικότητα Η κατάλληλη αρχικοποίηση του υποαντικειμένου, που αντιστοιχεί στην κλάση-κληροδότη, εξασφαλίζεται με την κατάλληλη κλήση του κατασκευαστή (costructor) της κλάσης-κληροδότη. Η κλήση προς τον κατασκευαστή γίνεται υπόρρητα από την Java, η οποία εισάγει αυτομάτως στο σώμα του κατασκευαστή τής κλάσηςκληρονόμου μια κλήση προς τον κατασκευαστή εκείνο τού κληροδότη, ο οποίος δεν επιδέχεται παραμέτρων. Η κλήση των κατασκευαστών σε μια σειρά κληρονομικότητας ξεκινάει από τον πιο απόμακρο κληροδότη, προχωρώντας προς τον τελευταίο κληρονόμο αφού: Tο αντικείμενο μιας κλάσης-κληροδότη πρέπει να έχει αρχικοποιηθεί πριν να μπορέσουν οι κατασκευαστές των κλάσεων-κληρονόμων να το χρησιμοποιήσουν. 29 Παράδειγμα cass Art { Art() { System.out.prit( à Art"); cass Drawig exteds Art { Drawig() { System.out.prit( à Draw"); pubic cass Cartoo exteds Drawig { Cartoo() { System.out.prit( à Cartoo"); pubic static void mai(strig[] args) { Cartoo x = ew Cartoo(); 30
cass Art { Art() { System.out.prit( à Art"); cass Drawig exteds Art { Drawig() { super(); System.out.prit( à Draw"); pubic cass Cartoo exteds Drawig{ Cartoo() { super(); System.out.prit( à Cartoo"); pubic static void mai(strig[] args) { Cartoo x = ew Cartoo(); Μ. Δικαιάκος, EΠΛ233 31 Κληρονομικότητα και Κατασκευαστές Στο προηγούμενο παράδειγμα και για όλες τις κλάσεις στην σειρά κληρονομικότητας που εξετάσαμε, έχουμε προκαθορισμένους (defaut) κατασκευαστές χωρίς παραμέτρους. Επομένως, η προκαθορισμένη συμπεριφορά της JAVA να εισαγάγει υπόρρητα κλήσεις προς τους κατασκευαστές των κληροδοτών, χωρίς πέρασμα παραμέτρων, δεν δημιουργεί πρόβλημα. Σε διαφορετική περίπτωση (υπερφόρτωση κατασκευαστών, απουσία προκαθορισμένου κατασκευαστή), ο προγραμματιστής πρέπει να καθορίσει ρητά την κλήση προς τον κατασκευαστή της κλάσης-κληροδότη, περνώντας και τις κατάλληλες παραμέτρους. Η κλήση ενός κατασκευαστή της υπερκλάσης γίνεται με χρήση της μεθόδου super(). 32 cass Game { Game(it i) { System.out.prit("Game costr"); cass BoardGame exteds Game { BoardGame(it i) { super(i); System.out.prit("BoardGame cost"); pubic cass Chess exteds BoardGame { Chess() { if ot used, compier super(11); ooks for super() System.out.prit("Chess costr"); pubic static void mai(strig[] args) { Chess x = ew Chess(); Μ. Δικαιάκος, EΠΛ233 33 Σύνθεση και Κληρονομικότητα pubic cass PaceSettig exteds Custom { Spoo sp; Fork frk; Kife k; DierPate p; PaceSettig(it i) { super(i + 1); sp = ew Spoo(i + 2); frk = ew Fork(i + 3); k = ew Kife(i + 4); p=ew DierPate(i + 5); pubic static void mai (Strig[] args) { PaceSettig x=ew PaceSettig(9); Ο μεταφραστής μας εξαναγκάζει να αρχικοποιήσουμε τους κληροδότες, αλλά εμείς πρέπει να φροντίσουμε για την αρχικοποίηση των αντικειμένων-στοιχείων. 34 Quiz cass Istrumet { Istrumet() { Άλλη εντολή πριν την Istrumet(it i) { this() δεν επιτρέπεται pubic cass Wid exteds Istrumet { Wid() { Wid(it i) { Μέσω της this(), καλείται // super(); o κατασκευαστής Wid(), ο οποίος με τη σειρά του καλεί τον Istrumet() this(); pubic static void mai(strig args[]) { Wid fute = ew Wid(8); Ποιός κατασκευαστής της Istrumet θα κληθεί ; Πόσες φορές ; 35 Απόκρυψη Ονομάτων cass Homer { char doh(char c) { System.out.prit("doh(char)"); retur 'd'; foat doh(foat f) { System.out.prit("doh(foat)"); retur 1.0f; pubic cass Hide { pubic static void mai(strig[] args){ Bart b = ew Bart(); b.doh(1); // doh(foat) used b.doh('x'); b.doh(1.0f); b.doh(ew Mihouse()); Η υπερφόρτωση λειτουργεί ανεξαρτήτως κληρονοµικότητας. cass Mihouse { cass Bart exteds Homer { void doh(mihouse m) { 36
Περίγραμμα Σύνθεση και Κληρονομικότητα Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia Σύνθεση : Η σύνθεση χρησιμοποιείται γενικότερα όταν χρειαζόμαστε τα χαρακτηριστικά μιας υπάρχουσας κλάσης και όχι την διαπροσωπεία της. Αντιστοιχεί σε has-a σχέσεις ανάμεσα στις κλάσεις. Κληρονομικότητα : Χρησιμοποιείται όταν θέλουμε να φτιάξουμε μιαν ειδική περίπτωση κάποιας κλάσης. Αν μια κλάση Β κληρονομεί από μια κλάση Α, η σχέση τους συνοψίζεται ως εξής : Η νέα κλάση Β είναι ένας τύπος της υπάρχουσας κλάσης Α. Αντιστοιχεί σε is-a σχέσεις ανάμεσα στις κλάσεις. 37 38 Αντιπροσώπευση - deegatio Αντιπροσώπευση - deegatio pubic cass SpaceShipCotros { void up(it veocity) { void dow(it veocity) { void eft(it veocity) { void right(it veocity) { void forward(it veocity) { void back(it veocity) { void turboboost() { Θέλουμε να δημιουργήσουμε μια κλάση SpaceShip, η οποία να εμπεριέχει τις λειτουργικότητες της SpaceShipCotros Ενδιάμεση λύση μεταξύ της σύνθεσης και της κληρονομικότητας: Τοποθέτηση αντικειμένου της αρχικής κλάσης (SpaceShipCotros) ως μέλους (πεδίου δεδομένων) στην κλάση που κατασκευάζουμε (SpaceShip). Έκθεση όλων των μεθόδων που μας ενδιαφέρουν από την αρχική κλάση μέσω των αντικειμένων της νέας κλάσης. Έτσι: Εμπεριέχεται αντικείμενο SpaceShipCotros στα μέλη του SpaceShip Αντικείμενα SpaceShip δίνουν άμεση πρόσβαση στις μεθόδους του SpaceShipCotros που χρειάζoνται 39 40 Αντιπροσώπευση - deegatio pubic cass SpaceShipCotros { void up(it veocity) { void dow(it veocity) { void eft(it veocity) { void right(it veocity) { void forward(it veocity) { void back(it veocity) { void turboboost() { pubic cass SpaceShipDeegatio{ private Strig ame; private SpaceShipCotros cotros = ew SpaceShipCotros(); pubic SpaceShipDeegatio(Strig ame) { this.ame = ame; pubic void back(it veocity) { cotros.back(veocity); pubic cass SpaceShip exteds SpaceShipCotros { private Strig ame; 41 Μ. Δικαιάκος, EΠΛ233 42
Περίγραμμα Προσδιοριστής πρόσβασης: protected Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia import java.uti.*; cass Viai { private it i; pubic Viai(it ii) { i = ii; protected it read() { retur i; protected void set(it ii) { i = ii; pubic it vaue(it m) { retur m*i; pubic cass Orc exteds Viai { private it j; pubic Orc(it jj) { super(jj); j = jj; pubic void chage(it x) { set(x); Η χρήση του protected σημαίνει ότι το αντίστοιχο στοιχείο μπορεί να χρησιμοποιηθεί μέσα στην βιβλιοθήκη στην οποία ανήκει, στις κλάσεις που κληρονομούν από την κλάση του στοιχείου, όχι όμως σε άλλες άσχετες κλάσεις. 43 44 Σύνοψη προσδιοριστών πρόσβασης Περίγραμμα Ορατότητα pubic protected defaut private Μέσα στην ίδια κλάση ναι ναι ναι ναι Κλάση στο ίδιο package ναι ναι ναι όχι Υποκλάση στο ίδιο package ναι ναι ναι όχι Υποκλάση εκτός package ναι ναι όχι όχι Οποιαδήποτε κλάση (όχι υποκλάση) εκτός package ναι όχι όχι όχι Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia 45 46 Αναβάθμιση κ. κληρονομικότητα Αναβάθμιση και κληρονομικότητα import java.uti.*; cass Istrumet { pubic void pay() { static void tue(istrumet i) { //... i.pay(); cass Wid exteds Istrumet { pubic static void mai(strig[] args){ Wid fute = ew Wid(); Istrumet.tue(fute); Υπάρχει λάθος; Upcastig Η κληρονομικότητα συνεπάγεται ότι οποιοδήποτε «μήνυμα» στέλνεται σε μια κλάση-κληροδότη, αυτό μπορεί να σταλεί και στις κλάσεις-κληρονόμους της. Αυτό σημαίνει ότι όλες οι προσβάσιμες (δημόσιες ή φιλικές) μέθοδοι που ανήκουν σε μια κλάσηκληροδότη, ενυπάρχουν και στις κλάσειςκληρονόμους της. Δεν συμβαίνει απαραίτητα και το αντίστροφο Επομένως, οι μέθοδοι pay και tue του παραδείγματός μας «υπάρχουν» και στα αντικείμενα τύπου Wid. 47 48
getname setname gethiredate sethiredate Αναβάθμιση - upcastig Παρατηρείστε ότι η tue καλείται από την Wid.mai με παράμετρο τύπου Wid χωρίς να παραπονεθεί ο μεταφραστής της Java. cass Wid exteds Istrumet { Wid fute = ew Wid(); Istrumet.tue(fute); Τι είναι το upcastig; Η αναβάθμιση ενός χειριστήριου τύπου Wid σε χειριστήριο τύπου Istrumet. Η μετατροπή γίνεται αυτόματα. Μ. Δικαιάκος, EΠΛ233 49 50 Αναβάθμιση Quiz Λόγω της κληρονομικότητας, ένα αντικείμενο τύπου Wid είναι επίσης αντικείμενο τύπου Istrumet. Στη διαπροσωπεία (iterface) του Wid υπάρχουν όλες οι μέθοδοι της διαπροσωπείας του Istrumet. package ep233; import java.uti.*; cass Istrumet { private static it k = 8; void pay() { System.out.prit( pay istrumet ); static void tue(istrumet i) { System.out.prit( Private k: + k); i.pay(); cass Wid exteds Istrumet { pubic static void mai(strig[] args) { Wid fute = ew Wid(); fute.k = 9; fute.tue(fute); Mήνυμα σφάλματος αφού δεν έχουμε πρόσβαση στην k 51 52 Περίγραμμα Η χρήση του fia Code re-use through compositio ad iheritace Iheritace ad hierarchy Οbject cass Η λέξη fia έχει διάφορες χρήσεις στην Java, αναλόγως των συμφραζομένων και αφορά σε: Δεδομένα. Μεθόδους Κλάσεις Exampe of iheritace Iheritace ad object costructio Code re-use through deegatio Iheritace ad access specifiers: protected Upcastig The keyword fia Γενικά σηματοδοτεί κάτι το οποίο δεν μπορεί ν αλλάξει. Δεδομένα fia: Με την fia μπορούμε να ορίζουμε σταθερές στην μεταφράση (compie-time costats), οι οποίες ανήκουν σε αρχέγονους τύπους. Μπορούμε επίσης να ορίζουμε σταθερές στην εκτέλεση (ru-time costats), οι οποίες αρχικοποιούνται κάποια στιγμή στον χρόνο εκτέλεσης και δεν αλλάζουν έκτοτε. Στην περίπτωση χειριστηρίων που καθορίζονται ως fia, τα ίδια τα χειριστήρια γίνονται «σταθερές», όχι όμως και τα περιεχόμενα των αντικειμένων στα οποία παραπέμπουν. Πεδία που ορίζονται σαν fia και static αντιστοιχούν σε μια μοναδική θέση μνήμης, τα περιεχόμενα της οποία δεν μπορούν να αλλαχθούν. 53 54
Παράδειγμα cass Vaue { it i = 1; pubic cass FiaData { fia it i1 = 9; static fia it VAL_TWO = 99; pubic static fia it VAL_THREE=39; fia it i4 =(it)(math.radom()*20); static fia it i5 = (it)(math.radom()*20); Vaue v1 = ew Vaue(); fia Vaue v2 = ew Vaue(); static fia Vaue v3 = ew Vaue(); // Arrays: fia it[] a = { 1, 2, 3, 4, 5, 6 ; Compie-time costats Typica pubic costat Ru-time costats Τελικές Παράμετροι cass Gizmo { pubic void spi() { pubic cass FiaArgumets { void with(fia Gizmo g) { g = ew Gizmo(); Προκύπτει σφάλμα: παράμετροι οι g.spi(); οποίες είναι fia δεν μπορούν να αλλαχθούν. void without(gizmo g) { g = ew Gizmo(); g.spi(); void f(fia it i) { i++; it g(fia it i) { retur i + 1; pubic static void mai(strig[] args) { FiaArgumets bf = ew FiaArgumets(); bf.without(u); bf.with(u); 55 56 Κενές Τελικές (Bak fias) Τελικές Μέθοδοι H Java επιτρέπει τον ορισμό πεδίων σαν fia, χωρίς να γίνεται αρχικοποίηση τους στο σημείο του ορισμού. Στην περίπτωση αυτή τα πεδία-σταθερές πρέπει να αρχικοποιηθούν μέσα στον κατασκευαστή της αντίστοιχης κλάσης διαφορετικά ο μεταφραστής διαμαρτύρεται. Έτσι, μας δίνεται η δυνατότητα να έχουμε διαφορετικές σταθερές μέσα σε διαφορετικά αντικείμενα της ίδιας κλάσης. Υπάρχουν δύο λόγοι για τους οποίους δηλώνουμε μια μέθοδο σαν fia: Για να αποτρέψουμε την αναίρεση (overwrittig) της μεθόδου μέσα από κάποια κλάση που την κληρονομεί, και να διατηρήσουμε έτσι το νόημά της. Για λόγους απόδοσης: ο κώδικας μεθόδων fia μπορεί να «ενσωματώνεται» (iie) από τον μεταφραστή στο κάθε σημείο κλήσης της μεθόδου. Κάθε ιδιωτική μέθοδος σε μια κλάση είναι υπορρήτως τελική αφού δεν επιτρέπεται πρόσβαση προς αυτήν από κάποιον κληρονόμο. 57 58 Ιδιωτικές και Τελικές Μέθοδοι Τελικές Κλάσεις pubic cass Test { fia void foo(it i) { pubic cass Test1 exteds Test { void foo(it j) { void foo(char c) { Προκύπτει σφάλμα στην μετάφραση (πού και γιατί); pubic cass Test { private void foo(it i) { pubic cass Test1 exteds Test { void foo(it j) { void foo(char c) { Δεν προκύπτει σφάλμα στην μετάφραση. Η δήλωση μιας κλάσης Foo ως fia, υποδηλώνει ότι η κλάση αυτή δεν μπορεί να κληροδοτηθεί σε άλλες κλάσεις. Κατ αυτόν τον τρόπο, δηλαδή, αποτρέπουμε την κληρονομικότητα από την Foo. 59 60
Αρχικοποίηση και Κληρονομικότητα cass Isect { it i = 9; it j; Isect() { prt("i = " + i + ", j = " + j); j=39; static it x1 = prt("static Isect.x1 iitiaized"); static it prt(strig s) { System.out.prit(s); retur 47; pubic cass Beete exteds Isect { it k = prt("beete.k iitiaized"); Beete() { prt("k = " + k); prt("j = " + j); static it x2 =prt("static Beete.x2 iitiaized"); pubic static void mai(strig[] args){ prt("beete costructor"); Beete b = ew Beete(); 61 Έξοδος Παραδείγματος static Isect.x iitiaized Static Beete.x2 iitiaized Beete costructor i = 9, j = 0 Beete.k iitiaized k = 47 i = 39 Βήματα στην εκτέλεση του jaba Beete: Φόρτωση της κλάσης Beete Αναζήτηση και Φόρτωση της ιεραρχίας των κληροδοτών της Beete (δηλαδή της Isect). Στατική αρχικοποίηση της Isect και μετά της Beete. Δημιουργία αντικειμένων και αρχικοποίηση πεδίων τους (σε u). Κλήση κατασκευαστών Αρχικοποίηση istace variabes Εκτέλεση εντολών κατασκευαστή 62 Πολλαπλή δήλωση της mai H μέθοδος mai μπορεί να οριστεί σε καθεμιά από τις κλάσεις μας. Αν σε ένα αρχείο Foo.java υπάρχουν πολλές κλάσεις και καθεμιά τους έχει ορισμένη μια διαφορετική mai, η κλήση java Foo θα προκαλέσει την εκτέλεση της mai που ορίζεται στην δημόσια κλάση του αρχείου (την Foo). Αν μέσα στο Foo.java ορίζεται η κλάση Goo, η οποία έχει μια δημόσια μέθοδο mai, τότε η κλήση java Goo θα εκτελέσει την μέθοδο Goo.mai(), έστω κι αν η Goo δεν είναι δημόσια. Ο ορισμός μεθόδων mai σε κάθε κλάση διευκολύνει ενίοτε τον έλεγχο της ορθότητας των κλάσεων. 63