JAVA ΕΝΟΤΗΤΑ 23 – DEFINING VARARGS METHODS

 


ΕΙΣΑΓΩΓΗ

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

FIXED NUMBER OF VARIABLES IN A METHOD

Με τη θεωρία που έχουμε αναλύσει σε προηγούμενα δωρεάν μαθήματα Java, γνωρίζουμε ότι για να δημιουργήσουμε σωστά μια μέθοδο, μια από τις απαιτήσεις είναι να ορίσουμε εξ αρχής όλες τις παραμέτρους που θα δέχεται. Η java όμως μας δίνει τη δυνατότητα να μπορούμε να δημιουργήσουμε μεθόδους στις οποίες ο αριθμός των μεταβλητών τους να μας είναι άγνωστος. Αυτή η νέα δυνατότητα ονομάζεται variable-length arguments ή αλλιώς varargs.

Ο καλύτερος τρόπος όμως για να εξηγήσουμε τη χρησιμότητα των varargs μεθόδων είναι να δούμε ένα απλό παράδειγμα. Ας δημιουργήσουμε μια κλάση με το όνομα MathUtil η οποία περιέχει μια μέθοδο με το όνομα max.

MathUtil.java

package com.args;

public class MathUtil {
    public int max(int x, int y) {
        int max = x;

        if (y > max) {
            max = y;
        }
        return max;
    }
}

Η μέθοδο max( ) δέχεται δύο int αριθμούς από τους οποίους μας επιστρέφει πίσω το μεγαλύτερο.

Δημιουργούμε μια δεύτερη κλάση με το όνομα MathUtilDemo μέσα στην οποία δημιουργούμε ένα αντικείμενο από τη κλάση MathUtil για να αποκτήσουμε πρόσβαση και να χρησιμοποιήσουμε τη μέθοδο max.

MathUtilDemo.java

package com.args;

public class MathUtilDemo {
    public static void main(String[] args) {
        MathUtil max_num = new MathUtil();
        int result = max_num.max(5, 10);
        System.out.println("The maximum number is: " + result);

    }
}

Output

The maximum number is: 10

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

Τώρα παρουσιάζεται η ανάγκη να καλύψουμε τη δυνατότητα να βρίσκουμε το μεγαλύτερο αριθμό ανάμεσα σε τρεις αριθμούς. Με βάση τη θεωρία του overloading θα μπορούσαμε να δημιουργήσουμε μια ακόμη μέθοδο με το ίδιο όνομα που θα δέχεται τρεις μεταβλητές. Η κλάση MathUtil τώρα θα περιέχει δύο max μεθόδους για να δώσει στο προγραμματιστή τη δυνατότητα να επιλέξει ποια από τις δύο θέλει να χρησιμοποιήσει.

MathUtil.java

package com.args;

public class MathUtil {
    public int max(int x, int y) {
        int max = x;

        if (y > max) {
            max = y;
        }
        return max;
    }

    public int max(int x, int y, int z) {
        int max = x;

        if (y > max) {
            max = y;
        }
        if (z > max) {
            max = z;
        }
        return max;
    }
}


Αφού προσθέσουμε το κώδικα της επιπλέον max μεθόδου στη κλάση MathUtil τώρα μπορούμε να δημιουργήσουμε το αντικείμενο μας από τη κλάση MathUtilDemo στο οποίο θα έχει προστεθεί μια καινούργια δυνατότητα.

MathUtilDemo.java

package com.args;

public class MathUtilDemo {
    public static void main(String[] args) {
        MathUtil max_num = new MathUtil();
        int twonumbers = max_num.max(5, 10);
        int threenumbers = max_num.max(5, 10, 15);
        System.out.println("The maximum number from 2 numbers: " + twonumbers);
        System.out.println("The maximum number from 3 numbers: " + threenumbers);

    }
}

Output

The maximum number from 2 numbers: 10

The maximum number from 3 numbers: 15

Με το ίδιο σκεπτικό, και βασιζόμενοι στη θεωρία του overloading, θα πρέπει να προσθέτουμε στη κλάση MathUtil καινούργιες μεθόδους αν υπάρχει η ανάγκη να συγκρίνουμε ένα μεγαλύτερο αριθμό μεταβλητών όπως 5 ή 8. Αυτό όμως σημαίνει πρακτικά ότι ο προγραμματιστής θα πρέπει να ξοδέψει αρκετό έξτρα χρόνο για να προσθέσει αυτές τις επιπλέον μεθόδους.

VARIABLE-LENGTH ARGUMENTS

Η Java (πιο συγκεκριμένα οι μηχανικοί της Java) αντιλήφθηκαν αυτή την αδυναμία και για αυτό το λόγο πρόσθεσαν στη γλώσσα τη δυνατότητα να μπορούμε να ορίζουμε μεθόδους με άγνωστο αριθμό μεταβλητών. Αυτό πρακτικά σημαίνει ότι αντί να δημιουργήσουμε μια μέθοδο που να δέχεται ένα int αριθμό και μετά μια δεύτερη μέθοδο που να δέχεται δύο int αριθμούς, να δημιουργήσουμε μόνο μια μέθοδο που να μπορεί να ανταποκριθεί στις ανάγκες μας ανεξάρτητα από το εύρος των μεταβλητών.

Ας δούμε λοιπόν πως θα μπορούσε να τροποποιηθεί η MathUtil κλάση χρησιμοποιώντας varargs σαν input στη μέθοδο.

MathUtil.java

package com.args;

public class MathUtil {
    public int max(int... num) {
        int max = 0;

        for (int i = 0; i < num.length; i++) {
            if (num[i] > max) {
                max = num[i];
            }
        }
        return max;
    }
}

Το να ορίσουμε μια μέθοδο που χρησιμοποιεί varargs μεταβλητή δεν χρειάζεται τίποτα άλλο από το να γράψουμε το data type, τρεις τελείες και τέλος το όνομα της μεταβλητής. Αυτός ο τρόπος μας επιτρέπει να καλέσουμε τη μέθοδο max με όσες παραμέτρους τύπου int επιθυμούμε συμπεριλαμβανομένου και του μηδέν – δηλαδή να μην περάσουμε καμία τιμή στη μέθοδο. Αν και στο δικό μας παράδειγμα, που συγκρίνουμε αριθμούς, να μην περάσουμε καμία τιμή στη μέθοδο δεν έχει και πολύ λογική, θεωρητικά το varargs μας το επιτρέπει.

 Αν προσέξετε τώρα τον κώδικα μέσα στο for loop, θα σας φανεί γνώριμος ο τρόπος με τον οποίο διαβάζουμε τον αριθμό των παραμέτρων και των αντίστοιχων τιμών που έχουν περαστεί στην μέθοδο. Εσωτερικά η Java αναγνωρίζει την var-args num μεταβλητή σαν array οπότε εμείς μπορούμε να χρησιμοποιήσουμε την λογική του index (όπως κάναμε και στους array) για να διαβάσουμε τις τιμές που έχουν περαστεί στην μέθοδο. Με την λογική αυτή λοιπόν, αν είχαμε περάσει τρεις τιμές, αυτές θα βρισκόντουσαν στο num[0], num[1], και num[2] αντίστοιχα. Επειδή όμως δεν γνωρίζουμε εξ αρχής πόσες τιμές θα περαστούν στην μέθοδο, για αυτό χρησιμοποιούμε το for loop και βρίσκουμε το μέγεθος του array από την ιδιότητα length.

Ας τρέξουμε πάλι την MathUtilDemo για να δούμε πως λειτουργεί το πρόγραμμα μας αν περάσουμε διαφορετικό αριθμό παραμέτρων κάθε φορά.

MathUtilDemo.java

package com.args;

public class MathUtilDemo {
    public static void main(String[] args) {
        MathUtil max_num = new MathUtil();
        int result1 = max_num.max(5, 10, 15);
        System.out.println("The maximum number is: " + result1);
        int result2 = max_num.max(5, 10, 15, 20);
        System.out.println("The maximum number is: " + result2);
        int result3 = max_num.max();
        System.out.println("The maximum number is: " + result3);

    }
}

Output

The maximum number is: 15

The maximum number is: 20

The maximum number is: 0


WHAT WE NEED TO BE CAREFUL WITH VARARGS

Η Java μας θέτει δύο περιορισμούς για το πως μπορούμε να ορίσουμε varargs μεθόδους.

1. Μπορούμε να χρησιμοποιήσουμε μόνο μια varargs μεταβλητή στην μέθοδο. Οπότε απαγορεύεται να κάνουμε κάτι όπως αυτό:

public int max(int...num1, int...num2){

//Code

}

2. Μπορούμε να χρησιμοποιήσουμε και άλλες παραμέτρους στον ορισμό της μεθόδου αρκεί όμως η varargs μεταβλητή να είναι τελευταία στην λίστα. Δηλαδή, μπορούμε να γράψουμε κάτι όπως:

public int max(int num1, int num2, int...num3){

//Code

}

Βασικά ο δεύτερος κανόνας εκτός από απαίτηση της java είναι και χρήσιμος γιατί με αυτό τον τρόπο μπορούμε να ζητήσουμε στα σίγουρα ένα συγκεκριμένο αριθμό δεδομένων (πχ. δύο τιμές) ενώ οποιοσδήποτε αριθμός τιμών πάνω από δύο να είναι προαιρετικός.

Τώρα ας θεωρήσουμε ότι καλύψαμε με μια varargs μέθοδο όλες τις int περιπτώσεις αλλά χρειαζόμαστε και τις double περιπτώσεις αριθμών. Οπότε χρειαζόμαστε ακόμα την λογική του overloading. Αυτό ισχύει με τις varargs μεθόδους? Φυσικά και ισχύει αρκεί να ικανοποιείται ο εξής απλός κανόνας – ότι το data type των παραμέτρων πρέπει να είναι διαφορετικός σε κάθε μια από τις μεθόδους.

MathUtil.java

package com.args;

public class MathUtil {
    public int max(int... num) {
        int max = 0;

        for (int i = 0; i < num.length; i++) {
            if (num[i] > max) {
                max = num[i];
            }
        }
        return max;
    }

    public double max(double... num) {
        double max = 0;

        for (int i = 0; i < num.length; i++) {
            if (num[i] > max) {
                max = num[i];
            }
        }
        return max;
    }
}


Υπάρχει όμως και η λογική ότι θα επιθυμούσατε να κάνετε overloading μια varargs μέθοδο με μια κανονική μέθοδο. Όπως το παρακάτω παράδειγμα:

MathUtil.java

package com.args;

public class MathUtil {

    public int max(int x, int y) {
        // Code
    }

    public int max(int... num) {
        // Code
    }
}


Μπορείτε να μαντέψετε ποια από τις δύο μεθόδους θα ενεργοποιηθεί αν καλέσουμε την max(2, 4)? Η java θα κοιτάξει πρώτα να δει αν υπάρχει κάποια μέθοδο με τον ακριβή αριθμό παραμέτρων και data type που μπορεί να εκτελέσει τις τιμές που περάστηκαν στην μέθοδο. Αν υπάρχει (που στο παράδειγμα μας υπάρχει) τότε θα εκτελεστεί αυτή η μέθοδος. Αν δεν υπάρχει τότε η java θα ανατρέξει στην varargs μέθοδο.

Τέλος, πριν ολοκληρώσουμε το σημερινό δωρεάν μάθημα Java, θα ήθελα να αναφερθώ στον τρόπο που πολλοί καινούργιοι προγραμματιστές γράφουν την μέθοδο main. Η main, όπως γνωρίζεται ήδη, δέχεται έναν array είδος String. Αυτός είναι ο πρώτος τρόπος με τον οποίο σχεδίασαν την java να μπορεί να δέχεται παραμέτρους ( τιμές με άλλα λόγια) από τον χρήστη κατά την διάρκεια εκτέλεσης του προγράμματος. Δηλαδή να μπορεί ο κώδικας σας να ρωτάει τον χρήστη να εισάγει κάποιες τιμές πριν συνεχίσει την εκτέλεση του. Τώρα που γνωρίζετε ότι εσωτερικά μια varargs μεταβλητή διαβάζεται από την java σαν array, μην σας φανεί παράξενο αν κάποιος γράψει την main κάπως έτσι.

MathUtilDemo.java

package com.args;

public class MathUtilDemo {
    public static void main(String... args) {
        MathUtil max_num = new MathUtil();
        int result = max_num.max(1, 2, 3);
        System.out.println("The maximum number is: " + result);
    }
}

Μην ξεχάσετε να κάνετε ένα μικρό donation έτσι ώστε αυτό το blog να μεγαλώσει ακόμα πιο πολύ και να έχει περισσότερες δυνατότητες στην online παράδοση δωρεάν μαθημάτων.

full-width

Post a Comment

0 Comments