FREE

ΕΝΟΤΗΤΑ 25 JAVA SE - METHOD OVERRIDING AND SUPER

Στο σημερινό δωρεάν μάθημα Java θα εξηγήσουμε τι ακριβώς είναι η διαδικασία overriding μιας μεθόδου και πως η λέξη κλειδί super συνδυάζεται με αυτή.

Για να μπορέσουμε να αναλύσουμε καλύτερα την θεωρία μας, θα συνεχίσουμε με το παράδειγμα του εργαζόμενου και θα χτίσουμε επάνω στις κλάσεις που ήδη έχετε γράψει.

Επειδή υπάρχει κληρονομικότητα ανάμεσα στις κλάσεις του παραδείγματος μας, μπορούμε να δημιουργήσουμε αντικείμενο είτε είδος Salary είτε είδος Manager. Για να δούμε τον μισθό του αντικειμένου Salary θα πρέπει να καλέσουμε την payment( ) μέθοδο, ενώ για να δούμε τον μισθό του Manager θα πρέπει να καλέσουμε την μέθοδο bonus( ) αντίστοιχα. Ας δούμε λοιπόν τι έχουμε μέχρι τώρα.

Employee.java

											
package overriding;

class Employee{
    public String name;
    public int AFM;
    public String department;
    public int employeeId;

    public void mailCheck(){
        System.out.println("Mailing a check to " + this.name);
    }
}
											

Salary.java

											
package overriding;

public class Salary extends Employee{

public float salary;

public double payment(){
    return this.salary/52.0;
}
}
											

Manager.java

											
package overriding;

public class Manager extends Salary{

    public double bonus(){
        return this.payment()+1000;

    }
}
											

EmployeeDemo.java

											
package overriding;

public class EmployeeDemo {
    public static void main(String []args){
        Manager m1 = new Manager();
        m1.name = "Michail";
        m1.department = "Development";
        m1.salary = 20000;
        System.out.println("Hello "+m1.name);
        System.out.println("Your payment plus your bonus is: " + m1.bonus());

    }
}
											

Output

											
    Hello Michail
    Your payment plus your bonus is: 1384.6153846153848
											

Αν και το πρόγραμμα μας δουλεύει για το σκοπό που δημιουργήθηκε (έχουμε παραλείψει έξτρα κώδικα όπως getter και setter μεθόδους), κάπως μπερδεύει τον προγραμματιστή όταν μέσα στην EmployeeDemo κλάση πρέπει να καλέσει ένα όνομα μεθόδου για να δει τον μισθό του Salary και διαφορετικό όνομα μεθόδου για να δει τον μισθό του Manager. Σε μια αρκετά μεγάλη εφαρμογή με εκατοντάδες κλάσεις αυτό θα είναι λίγο δύσκολο να το ακολουθήσει κάποιος. Το επιθυμητό θα ήταν να υπάρχει μια κοινή μέθοδο για όλες τις κλάσεις, όπως για παράδειγμα payment( ). Μέσα σε κάθε κλάση η payment( ) θα περιέχει τον αντίστοιχο κώδικα που αντιπροσωπεύει την σωστή πληροφορία είτε είναι για τον Salary είτε για τον Manager. Το τελικό αποτέλεσμα θα είναι να υπάρχει μια μέθοδος με το ίδιο όνομα (αλλά διαφορετικό κώδικα) σε όλες τις κλάσεις. Με αυτό τον τρόπο από όποια κλάση και αν κάνουμε αντικείμενο θα γνωρίζουμε ότι καλώντας την payment( ) μέθοδο θα πάρουμε τον μισθό του αντίστοιχου αντικειμένου.

Στην Java, ο πρακτικός τρόπος να δώσουμε αυτή την δομή στο πρόγραμμα μας είναι να ξαναγράψουμε τον κώδικα για μεθόδους που κληρονομούμε. Αυτή την διαδικασία την ονομάζουμε method overriding γιατί πολύ απλά γράφεις ξανά τον κώδικα της μεθόδου που κληρονομείς κρατώντας ίδιο το signature. Αυτή την δυνατότητα την έχουμε λόγω της κληρονομικότητας.

Όταν όμως κάνουμε override μια μέθοδο, η java θέλει να ακολουθήσουμε τρεις απλούς κανόνες:

  • Το signature της μεθόδου, δηλαδή το return type, method name και parameter list πρέπει να παραμείνουν τα ίδια
  • Ο access specifier πρέπει να είναι τουλάχιστον ίδιος, ή πιο χαλαρός με εκείνον της κλάσης από την οποία κληρονόμησες την μέθοδο. Δηλαδή αν έχουμε κληρονομήσει μια μέθοδο που έχει access specifier protected, τότε στην δική μας κλάση μπορούμε να δώσουμε είτε τον ίδιο access specifier στην μέθοδο ή πιο χαλαρό όπως public, όχι όμως private. Με την ίδια λογική εάν κληρονομήσουμε μια μέθοδο με public access specifier τότε θα πρέπει και εμείς να κρατήσουμε το public.
  • Τέλος, δεν επιτρέπεται από την java, η δική μας μέθοδο να επιστρέφει περισσότερα exceptions από την αρχική. Για τα exceptions θα μιλήσουμε σε μελλοντική ενότητα.

Προσέξτε με τους δύο όρους override και overload. Το overload όπως έχουμε ήδη εξηγήσει σε προηγούμενη ενότητα, σημαίνει ότι αλλάζω τον αριθμό και είδος των παραμέτρων (parameter list) σε μια μέθοδο ενώ κρατάω ίδιο μόνο το όνομα της. Το override σημαίνει ότι αφήνω τον ορισμό της μεθόδου αυτούσιο και απλά αλλάζω τον κώδικα που περιέχει ή προσθέτω επιπλέον κώδικα σε αυτόν που ήδη περιέχει.

Στο δικό μας παράδειγμα λοιπόν, θα μπορούσαμε αντί να γράψουμε μια καινούργια μέθοδο bonus( ) μέσα στην κλάση Manager, να κάναμε override την μέθοδο payment που κληρονομούμε από την Salary και να αλλάξουμε τον κώδικα της έτσι ώστε να δείχνει τον σωστό κώδικα για την κλάση Manager. Το τελικό αποτέλεσμα είναι ότι όταν πάμε στην κλάση EmployeeDemo να δημιουργήσουμε αντικείμενο είτε από κλάση Salary είτε από την κλάση Manager, η μέθοδος payment( ) θα σας δώσει το σωστό αποτέλεσμα για το κάθε αντικείμενο. Ας δούμε λοιπόν πως αλλάζει ο κώδικας μας. Αυτή η αλλαγή θα γίνει κυρίως στην Manager (μέσα στην οποία θα κάνουμε το override).

Manager.java

											
package overriding;

public class Manager extends Salary{

    @Override
    public double payment(){
    return this.salary/52.0+1000;
}
}
											
                        

EmployeeDemo.java

											
package overriding;

public class EmployeeDemo {
    public static void main(String []args){
        Manager m1 = new Manager();
        m1.name = "Michail";
        m1.department = "Development";
        m1.salary = 20000;
        System.out.println("Hello "+m1.name);
        System.out.println("Your payment plus your bonus is: " + m1.payment());

    }
}
											
                        

Output

											
Hello Michail
Your payment plus your bonus is: 1384.6153846153848
											
                        

Αν και στην κλάση Manager κάναμε override την μέθοδο payment γράφοντας τον δικό μας κώδικα, για ακόμη μια φορά δεν είμαστε ικανοποιημένοι γιατί πολύ απλά γράψαμε όλο τον κώδικα της payment από την αρχή και στο τέλος προσθέσαμε το bonus. Το ιδανικό σενάριο θα ήταν να καλούσαμε την μέθοδο payment όπως έχει γραφτεί στην Salary και απλά να προσθέσουμε τον έξτρα κώδικα. Αυτό ακριβώς μας επιτρέπει να κάνουμε η λέξη super. Με την super μπορούμε να καλέσουμε μεταβλητές ή μεθόδους από την οποία κληρονομούμε. Προσέξτε, αναφερόμαστε στην αμέσως προηγούμενη κλάση από την οποία κληρονομούμε και όχι οποιαδήποτε κλάση στο δέντρο κληρονομικότητας το οποίο ίσως αποτελείται από πολλαπλές κλάσεις.

Με αυτή την λογική λοιπόν μπορούμε να αλλάξουμε τον κώδικα της payment μεθόδου μέσα στην κλάση Manager ως εξής:

Manager.java

											
package overriding;

public class Manager extends Salary{

    @Override
    public double payment(){
    return super.payment()+1000;
}
}
											
    

Τώρα έχουμε την δυνατότητα να χρησιμοποιήσουμε αυτούσιο τον κώδικα της μεθόδου από την προηγούμενη κλάση την οποία κληρονομούμε και απλά να προσθέσουμε τον έξτρα κώδικα που χρειαζόμαστε. Δεν χρειάζεται να κάνετε καμία αλλαγή στην EmployeeDemo κλάση και το αποτέλεσμα θα είναι ακριβώς το ίδιο.