java:inheritance

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Next revision Both sides next revision
java:inheritance [2015/02/13 12:17]
gthanos created
java:inheritance [2016/02/12 15:51]
gthanos [Implicit και Explicit Casting of Objects]
Line 1: Line 1:
 ====== Κληρονομικότητα ====== ====== Κληρονομικότητα ======
  
-Σε προηγούμενη παράγραφοαναφερόμενοι στην κλάση [[:java:class:Κληρονομικότητα ​Κλάσης ​έγινε αναφορά και στην κληρονομικότητα κλάσεων]] στην Java. +Βασικό χαρακτηριστικό του αντικειμενοστραφούς ​προγραμματισμού είναι η δυνατότητα να παράγουμε νέες κλάσεις με βάση υφιστάμενες κλάσεις,​ εξειδικεύοντας και επεκτείνοντας τα χαρακτηριστικά των υφιστάμενων. Η διαδικασία επέκτασης των υφιστάμενων κλάσεων σε νέες ειδικότερες κλάσεις ​ονομάζεται κληρονομικότητα
 + 
 +Κάθε κλάση που κληρονομεί από μία άλλη κλάση ονομάζεται υποκλάση (//​subclass//​) της γονικής κλάσης από την οποία κληρονομεί. Αντίστοιχα, η γονική κλάση ονομάζεται υπερκλάση (//​superclass//​) της κληρονομούμενης ​κλάσης. 
 + 
 +{{  :​java:​super_sub_class.jpg ​ | }} 
 + 
 +Όπως φαίνεται και στο παραπάνω σχήμα μία κλάση (//​subclass//​) μπορεί να κληρονομεί __**ΜΟΝΟ ΜΙΑ**__ άλλη κλάση. Αντίστροφα μία κλάση (//​superclass//​) μπορεί να κληρονομείται από πολλές διαφορετικές κλάσεις. Παρακάτω δίνουμε ένα παράδειγμα κληρονομικότητας από το site της ​[[https://​docs.oracle.com/​javase/​tutorial/​java/​IandI/​subclasses.html|Oracle]],​ όπου η κλάση ''​MountainBike''​ αποτελεί εξειδίκευση της κλάσης ''​Bicycle''​. 
 + 
 +<code java Bicycle.java>​ 
 +public ​class Bicycle { 
 +         
 +    private int cadence; 
 +    private int gear; 
 +    private int speed; 
 +        
 +    public Bicycle(int startCadence,​ int startSpeed, int startGear) { 
 +        gear = startGear;​ 
 +        cadence = startCadence;​ 
 +        speed = startSpeed;​ 
 +    } 
 +     
 +    public int getCadence() { 
 +          return cadence; 
 +    } 
 +     
 +    public int getGear() { 
 +          return gear; 
 +    } 
 +     
 +    public int getSpeed() { 
 +          return speed; 
 +    } 
 + 
 +    public void setCadence(int newValue) { 
 +        cadence = newValue; 
 +    } 
 +         
 +    public void setGear(int newValue) { 
 +        gear = newValue; 
 +    } 
 +         
 +    public void applyBrake(int decrement) { 
 +        speed -= decrement;​ 
 +    } 
 +         
 +    public void speedUp(int increment) { 
 +        speed += increment;​ 
 +    } 
 +         
 +
 +</​code>​ 
 + 
 +<code java MountainBike.java>​ 
 +public class MountainBike extends Bicycle { 
 + 
 +    private int seatHeight;​ 
 + 
 +    // the MountainBike subclass has 
 +    // one constructor 
 +    public MountainBike(int startHeight,​ int startCadence,​ 
 +                        int startSpeed, int startGear) { 
 +        super(startCadence,​ startSpeed, startGear);​ 
 +        seatHeight = startHeight;​ 
 +    }    
 +         
 +    // the MountainBike subclass has 
 +    // one method 
 +    public void setHeight(int newValue) { 
 +        seatHeight = newValue; 
 +    } 
 +     
 +    public int getSeatHeight() { 
 +        return seatHeight;​ 
 +    } 
 +
 +</​code>​ 
 + 
 +===== Προσβασιμότητα των κληρονομούμενων πεδίων ===== 
 + 
 +Μία κλάση η οποία κληρονομεί μία άλλη κλάση έχει πρόσβαση στα μέλη (πεδία και μεθόδους) της κλάσης αυτής ως εξής: 
 + 
 +  * Έχει πρόσβαση στα //​**public**//​ και //​**protected**//​ μέλη της γονικής κλάσης 
 +  * Έχει πρόσβαση στα //**package private**// μέλη (δηλ. τα μέλη χωρίς προσδιοριστή πρόσβασης) μόνο αν βρίσκεται στο ίδιο πακέτο με την γονική κλάση. 
 +  * Δεν έχει πρόσβαση στα //​**private**//​ μέλη της κλάσης.  
 + 
 +Αν υπάρχουν //​**public**//​ μέθοδοι οι οποίες επιτρέπουν την πρόσβαση σε //​**private**//​ πεδία, τότε αυτές μπορούν να χρησιμοποιηθούν για τον ορισμό ή για την λήψη της τιμής τους. 
 + 
 +===== Τι μπορούμε να κάνουμε σε μία υποκλάση... ===== 
 + 
 +  * Να χρησιμοποιήσουμε τα πεδία της γονικής κλάσης στα οποία ​έχουμε πρόσβαση (public, protected, package-private στο ίδιο package). 
 +  * Να ορίσουμε νέα πεδία. 
 +  * Να ορίσουμε νέα πεδία που να έχουν ίδιο όνομα με πεδία της ​γονικής κλάσης. Σε αυτή την περίπτωση "​κρύβουμε"​ τα πεδία της γονικής κλάσης. Η συγκεκριμένη πρακτική δεν συνίσταται και παραπέμπει σε λανθασμένη σχεδίαση κώδικα. 
 +  * Να χρησιμοποιήσουμε τις μεθόδους της γονικής κλάσης στις οποίες έχουμε πρόσβαση (public, protected, package-private στο ίδιο package). 
 +  * Μπορούμε να γράψουμε νέες στατικές ή μη στατικές μεθόδους για τη υποκλάση. 
 +  * Μπορούμε να γράψουμε νέες μεθόδους που έχουν το ίδιο //​signature//​ (ίδιο όνομα, ίδιο αριθμό και ίδιο τύπο ορισμάτων),​ ώστε να επαναορίσουμε (//​override//​) τις μεθόδους αυτές ​στην ​υποκλάση. Η πρακτική αυτή είναι συνήθης. 
 +  * Μπορούμε ​να γράψουμε νέες στατικές (//​static//​) μεθόδους που έχουν το ίδιο //​signature//,​ ώστε να επαναορίσουμε (//​override//​) τις μεθόδους αυτές στην υποκλάση. Επαναορίζοντας στατικές μεθόδους,​ κρύβουμε τις αντίστοιχες μεθόδους της γονικής ​κλάσης. 
 +  * Μπορούμε να γράψουμε κατασκευαστές της υποκλάσης που χρησιμοποιούν κατασκευαστές της γονικής κλάσης. 
 + 
 + 
 +===== Final Κλάσεις και Μέθοδοι ===== 
 + 
 +Μπορείτε να δηλώσετε μία ή περισσότερες μεθόδους μία κλάσης ​ως //final//. Δηλώνοντας μία μέθοδο ως final η μέθοδος αυτή δεν μπορεί να επαναοριστεί σε μία υποκλάση της κλάσης αυτής. Ο συχνότερος λόγος για να δηλώσετε μία μέθοδο ως //final// είναι αν η υλοποίηση της μεθόδου δεν πρέπει να αλλάξει. Ένα παράδειγμα είναι το παρακάτω:​ 
 + 
 +<code java> 
 +class ChessAlgorithm { 
 +    enum ChessPlayer { WHITE, BLACK } 
 +    ... 
 +    final ChessPlayer getFirstPlayer() { 
 +        return ChessPlayer.WHITE;​ 
 +    } 
 +    ... 
 +
 +</​code>​ 
 + 
 +Γενικότερα,​ μέθοδοι που καλούνται από τους κατασκευαστές της κλάσης __θα πρέπει__ να ορίζονται ως //final// καθώς αν αλλάζουν την υλοποίηση τους σε υποκλάσεις μπορούν να δημιουργηθούν προβλήματα ως προς την ορθή αρχικοποίηση των μεταβλητών της κλάσης. 
 + 
 +Τέλος, μπορείτε να προσδιορίσετε μία κλάση ως //final//, όταν θέλετε να δηλώσετε ότι η συγκεκριμένη κλάση δεν πρέπει να έχει υποκλάσεις. Ένα παράδειγμα τέτοια κλάσης είναι η κλάση [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​String.html | String]] της standard βιβλιοθήκης της ​Java. 
 + 
 +|Προηγούμενο:​ [[ :​java:​interfaces | Διεπαφές ]] | Επόμενο:​ [[ :​java:​multiple_inheritance | Κληρονομικότητα πολλαπλών γονικών κλάσεων ]]|
  
java/inheritance.txt · Last modified: 2016/03/31 08:25 by doufexi