Χρήστης:George Chatz/sandbox2

Από τη Βικιπαίδεια, την ελεύθερη εγκυκλοπαίδεια

{{τεχνικό|@=20/2/2012}}

Στον αντικειμενοστραφή προγραμματισμό υπολογιστών, η υπερφόρτωση τελεστών—σπανιότερα γνωστή και ως ad-hoc πολυμορφισμός τελεστών—είναι μια ειδική περίπτωση πολυμορφισμού, όπου διαφορετικοί τελεστές έχουν διαφορεικές υλοποιήσεις αναλόγως των ορισμάτων τους. Η υπερφόρτωση τελεστών εν γένει ορίζεται από τη γλώσσα, τον προγραμματιστή, ή και τα δύο.

Υποστηρίζεται ότι η υπερφόρτωση τελεστών είναι χρήσιμη επειδή επιτρέπει στον προγραμματιστή να προγραμματίσει χρησιμοποιώντας σημειογραφία "πιο κοντά στο πεδίο του σκοπού" ("closer to the target domain")[1] και επιτρέπει σε τύπους που έχουν οριστεί από το χρήστη συντακτική υποστήριξη στο ίδιο επίπεδο με τους τύπους που είναι ενσωματωμένοι στη γλώσσα. Μπορεί εύκολα να προσομοιωθεί με τη χρήση κλήσεων συναρτήσεων. Για παράδειγμα, αν θεωρήσουμε τους ακεραίους a, b, c:

a + b * c

Σε μια γλώσσα που υποστηρίζει υπερφόρτωση τελεστών, και θεωρώντας ότι ο τελεστής '*' έχει υψηλότερη προτεραιότητα από τον τελεστή '+', η γραφή αυτή είναι ένας πιο συνοπτικός τρόπος από το να γράψουμε:

add (a, multiply (b,c))

Παραδείγματα[Επεξεργασία | επεξεργασία κώδικα]

Σε αυτή την περίπτωση, ο τελεστής της πρόσθεσης υπερφορτώνεται ώστε να επιτρέπει την πρόσθεση ενός ορισμένου από το χρήστη τύπου "Time" (σε C++):

Time operator+(const Time& lhs, const Time& rhs) 
{
    Time temp = lhs;
    temp.seconds += rhs.seconds;
    if (temp.seconds >= 60) {
        temp.seconds -= 60;
        temp.minutes++;
    }
    temp.minutes += rhs.minutes;
    if (temp.minutes >= 60) {
        temp.minutes -= 60;
        temp.hours++;
    }
    temp.hours += rhs.hours;
    return temp;
}

Η πρόσθεση είναι μια δυαδική πράξη, το οποίο σημαίνει ότι έχει ένα δεξιό κι ένα αριστερό όρισμα. Στη C++, τα ορίσματα που περνάμε είναι τα ορίσματα της πράξης, και το αντικείμενο temp είναι η επιστρεφόμενη τιμή.

Η πράξη θα μπορούσε επίσης να οριστεί ως μέθοδος κάποιας κλάσης, αντικαθιστώντας το lhs με το κρυμένο όρισμα this. Ωστόσο, αυτό αξαναγκάζει το αριστερό όρισμα να είναι τύπου Time και υποθέτει ότι το this είναι πιθανώς μια μεταβλητή lvalue:

Time Time::operator+(const Time& rhs) const 
{
    Time temp = *this;  /* Copy 'this' which is not to be modified */
    temp.seconds += rhs.seconds;
    if (temp.seconds >= 60) {
        temp.seconds -= 60;
        temp.minutes++;
    }
    temp.minutes += rhs.minutes;
    if (temp.minutes >= 60) {
        temp.minutes -= 60;
        temp.hours++;
    }
    temp.hours += rhs.hours;
    return temp;
}

Σημειώνεται ότι ένας μοναδιαιος τελεστής ορίσμένος ως μέθοδος κάποιας κλάσης δε θα δεχόταν κανένα όρισμα (δουλεύει μόνο με το this):

bool Time::operator!() const 
{
    return ((hours == 0) && (minutes == 0) && (seconds == 0));
}

Κριτική[Επεξεργασία | επεξεργασία κώδικα]

Η υπερφόρτωση τελεστών συχνά δέχεται κριτική επειδή επιτρέπει στους προγραμματιστές να δίνουν στους τελεστές εντελώς διαφορετική σημασία αναλόγως του τύπου των ορισμάτων. Για παράδειγμα η χρήση του << στον παρακάτω κώδικα C++:

a << 1

ολισθαλινει τα bits της μεταβλητής a αριστερά κατά 1 bit εφόσον η μεταβλητή a είναι ακεραίου τύπου, αλλά αν η μεταβλητή a είναι ροή εξόδου (output stream) τότε η παραπάνω εντολή θα προσπαθήσει να γράψει "1" στη ροή. Επειδή η υπερφόρτωση υποτύπων επιτρέπει στον αρχικό προγραμματιστή να αλλάξει τη συνήθη σημασιολογία ενός τελεστή και να φέρει προ εκπλήξεων μελλοντικούς προγραμματιστές, είθισται να θεωρείται καλή πρακτική η χρήση υπερφόρτωσης τελεστών με προσοχή.

Η συνήθης απάντηση στην κριτική αυτή είναι ότι το ίδιο ισχύει και για την υπερφόρτωση συναρτήσεων. Επιπλέον, ακόμα και χωρίς την ύπαρξη υπερφόρτωσης, ο προγραμματιστής μπορεί να ορίσει μια συνάρτηση για να κάνει κάτι διαφορετικό από αυτό που υποδεινύει το όονμά της. Ένα θέμα που παραμένει είναι ότι γλώσσες όπως η C++ προσφέρουν ένα περιορισμένο σύνολο συμβόλων-τελεστών, αφαιρώντας έτσι από τους προγραμματιστές την επιλογή κάποιου πιο ταιριαστού συμβόλου για μια νέα πράξη.

Ένα άλλο, πιο λεπτό θέμα με τους τελεστές είναι ότι συγκεκριμένοι κανόνες από τα μαθηματικά μπορεί αναμένονται, ή (εσφαλμένα) να θεωρούνται δεδομένοι. Για παράδειγμα η αντιμεταθετικότητα του + (π.χ. ότι a + b == b + a) δεν ισχύει πάντα. Ένα τέτοιο παράδειγμα είναι όταν τα ορίσματα είναι συμβολοσειρές, εφόσον το + συχνά είναι υπερφορτωμένο ώστε να εκτελεί τη συνένωση συμβολοσειρών (π.χ. το "school" + "bag" έχει ως αποτέλεσμα τη συμβολοσειρά "schoolbag", η οποία είναι διαφορετική από το "bag" + "school" που έχει ως αποτέλεσμα τη συμβολοσειρά "bagschool"). Μια χαρακτηριστική απάντηση σε αυτό το επιχείρημα έρχεται από τα μαθηματικά: ενώ το + είναι αντιμεταθετικό στους ακεραίους (και εν γένει σε όλους τους πραγματικούς αριθμούς), δεν είναι αντιμεταθετικό για άλλους "τύπους" μεταβλητών. Επιπλέον μπορεί να σημειωθεί ότι το + δεν είναι αντιμεταθετικό ούτε για πραγματικούς αριθμούς στην πράξη λόγω λαθών στρογγυλοποίησης. Ένα άλλο παράδειγμα: η δυαδική πράξη * (πολλαπλασιασμός) είναι αντιμεταθετική για ακέραιους αλλά όχι για πίνακες πολλαπλασιασμός πινάκων.

Κατάλογος[Επεξεργασία | επεξεργασία κώδικα]

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

Τελεστές Μη υπερφορτώσιμες Υπερφορτώσιμες
Ορισμός νέων
Περιορισμένο σύνολο

Ιστορικό της υπερφόρτωσης τελεστών[Επεξεργασία | επεξεργασία κώδικα]

1960s[Επεξεργασία | επεξεργασία κώδικα]

Η προδιαγραφή της ALGOL 68 επέτρεπε την υπερφόρτωση τελεστών.[7]

Απόσπασμα από την προδιαγραφή της γλώσσας ALGOL 68 (σελίδα 177) όπου ορίζονται οι υπερφορτωμένοι τελεστές ¬, =, ≠ και abs:

10.2.2. Operations on Boolean Operands
a) op ∨ = (bool a, b) bool:( a | true | b );
b) op ∧ = (bool a, b) bool: ( a | b | false );
c) op ¬ = (bool a) bool: ( a | false | true );
d) op = = (bool a, b) bool:( a∧b ) ∨ ( ¬b∧¬a );
e) op ≠ = (bool a, b) bool: ¬(a=b);
f) op abs = (bool a)int: ( a | 1 | 0 );

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

1980s[Επεξεργασία | επεξεργασία κώδικα]

Η Ada υποστηρίζει υπερφόρτωση τελεστών εξ αρχής, με την έκδοση του προτύπου της γλώσσας Ada 83. Ωστόσο, οι σχεδιαστές της γλώσσας επέλεξαν να μην επιτρέψουν τον ορισμό νέων τελεστών: μόνο οι υπάρχοντες τελεστές της γλώσσας μπορούν να υπερφορτωθούν (με τον ορισμό νέων συναρτήσεων με αναγνωριστικά όπως τα "+", "*", "and", κλπ.). Οι μετέπειτα αναθεωρήσεις της γλώσσας (το 1995 και το 2005) διατηρούν τον περιορισμό στην υπερφόρτωση υπάρχοντων τελεστών.

Η υπερφόρτωση τελεστών στη C++ είναι ακόμα πιο λεπτή από αυτή της ALGOL 68.[8]

1990s[Επεξεργασία | επεξεργασία κώδικα]

Η Sun επιλέγει να μην περιλάβει την υπερφόρτωση τελεστών στη γλώσσα Java.[9][10]

Η γλώσσα προγραμματισμού Ruby επιτρέπει την υπερφόρτωση τελεστών ως συντακτική ζάχαρη (syntactic sugar) για απλές κλήσεις μεθόδων.

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

2000's[Επεξεργασία | επεξεργασία κώδικα]

Η Microsoft περιλαμβάνει την υπερφόρτωση τελεστών στη C# το 2001.

Η γλώσσα προγραμματισμού Scala επιτρέπει την υπερφόρτωση τελεστών μέσω της πολλαπλής αποστολής.

Δείτε Επίσης[Επεξεργασία | επεξεργασία κώδικα]

Αναφορές[Επεξεργασία | επεξεργασία κώδικα]

  1. «C++ FAQ Lite: What are the benefits of operator overloading?». 2010. Ανακτήθηκε στις Αύγουστος 2010.  Unknown parameter |month= ignored (βοήθεια); Ελέγξτε τις τιμές ημερομηνίας στο: |accessdate= (βοήθεια)
  2. binary functions with a symbolic name can be called infix
  3. introduced in Fortran 90
  4. type classes instead of overloading
  5. «Why does Go not support overloading of methods and operators?». Ανακτήθηκε στις 4 Σεπτεμβρίου 2011. 
  6. «Operator Overloading, Free Pascal Manual». Ανακτήθηκε στις Ιούνιος 2011.  Ελέγξτε τις τιμές ημερομηνίας στο: |accessdate= (βοήθεια)
  7. A. van Wijngaarden, B.J. Mailloux, J.E.L. Peck and C.H.A. Koster· και άλλοι. (1968). «Report on the Algorithmic Language ALGOL 68, Section 10.2.2» (PDF). Ανακτήθηκε στις Απρίλιος 2007.  Unknown parameter |month= ignored (βοήθεια); Ελέγξτε τις τιμές ημερομηνίας στο: |accessdate= (βοήθεια)CS1 maint: Explicit use of et al. (link) CS1 maint: Πολλαπλές ονομασίες: authors list (link)
  8. Bjarne Stroustrup. «A History of C++: 1979−1991 - page 12» (PDF). Ανακτήθηκε στις Απρίλιος 2007.  Ελέγξτε τις τιμές ημερομηνίας στο: |accessdate= (βοήθεια)
  9. [1]
  10. [2]

[[Κατηγορία:Άρθρα με παραδείγματα κώδικα ALGOL 68]] [[Κατηγορία:Τελεστές (προγραμματισμός)]] {{ενσωμάτωση κειμένου|en|Operator overloading}} [[de:Überladen]] [[fa:سربارگزاری عملگرها]] [[fr:Surcharge des opérateurs]] [[ko:연산자 오버로딩]] [[mk:Преоптоварување на оператор]] [[nl:Operator-overloading]] [[pl:Przeciążanie operatorów]] [[ru:Перегрузка операторов]] [[uk:Перевантаження операторів]] [[zh:运算符重载]]