Δυναμική αποστολή (υπολογιστές)

Στην επιστήμη των υπολογιστών και συγκεκριμένα στο αντικειμενοστρεφή προγραμματισμό η δυναμική αποστολή (Αγγλικά: Dynamic dispatch) είναι μια διαδικασία κατά την υλοποίηση μιας πολυμορφικής ενέργειας (μεθόδου ή συνάρτησης) που καλείται κατά τον χρόνο εκτέλεσης. Η δυναμική αποστολή έχει διαφορά με την στατική αποστολή (αγγλικά: static dispatch) η οποία υλοποιεί μια πολυμορφική ενέργεια κατά την διάρκεια της μεταγλώττισης του κώδικα. Ο στόχος της δυναμικής αποστολής είναι η υποστήριξη περιπτώσεων όπου η πολυμορφική ενέργεια δεν μπορεί να καθοριστεί κατά την διάρκεια του χρόνου μεταγλώττισης αλλά εξαρτάται από τις συνθήκες και τις παραμέτρους που καθορίζονται στον χρόνο εκτέλεσης.[1][2]

Γενικά ο όρος δέσμευση ή σύνδεση (Αγγλικά: binding) αναφέρεται στον τρόπο που γίνεται η κλήση μιας μεθόδου και του συσχετισμού με τον κώδικά της. Κατά τον μηχανισμό καθυστερημένης δέσμευσης (Αγγλικά: late binding) ο κώδικας της μεθόδου συσχετίζεται κατά την εκτέλεση του κώδικα (Αγγλικά: runtime). Στην Java χρησιμοποιείται για κάθε κλήση μεθόδων ως προεπιλογή ο μηχανικός καθυστερημένης δέσμευσης με εξαίρεση τις private, final και static μεθόδους.[3] Στην C++ χρησιμοποιείται η τεχνική πρώιμης δέσμευσης (Αγγλικά: early binding) όπου ο κώδικας της μεθόδου συσχετίζεται κατά την μεταγλώττιση του κώδικα (Αγγλικά: compile time). Στην C++ χρησιμοποιείται ως προεπιλογή η στατική αποστολή (Αγγλικά: static dispatch) και η δυναμική αποστολή γίνεται όταν ορίζουμε μια μέθοδο ως virtual και για να υλοποιηθεί η δυναμική αποστολής ένας πίνακας συσχέτισης υπερβατικών συναρτήσεων (Αγγλικά: virtual method table) vtable .[4][5]

Παραδείγματα

Java

Στο παρακάτω παράδειγμα στην γλώσσα προγραμματισμού Java έχουμε ένα παράδειγμα δυναμικής αποστολής με δύο κλάσεις όπου έχουν την ίδια συνάρτηση void print() και η μια κληρονομεί την άλλη (η κλάση "Paidi" επεκτείνει την κλάση "Pateras"). Η επιλογή της κλήσης void print() επιλέγεται στο χρόνο εκτέλεσης μέσω της δυναμικής αποστολής [6]:

class Pateras {   void print() {      System.out.println("Κλήση του πατέρα.");   }}class Paidi extends Pateras {   void print() {      System.out.println("Κλήση του παιδιού.");   }}public class ex_dynamic_dispatch {   public static void main(String args[]) {      Pateras oPateras = new Pateras();      // αντικείμενο της κλάσης Pateras      Paidi toPaidi = new Paidi();           // αντικείμενο της κλάσης Paidi      Pateras EnaAntikeimeno;                // Ορισμός ενός αντικειμένου της κλάσης Pateras      EnaAntikeimeno=oPateras;               // Το EnaAntikeimeno είναι μια αναφορά στο αντικείμενο oPateras      EnaAntikeimeno.print();                // Τυπώνει: "Κλήση του πατέρα."      EnaAntikeimeno=toPaidi;      EnaAntikeimeno.print();                // Τυπώνει: "Κλήση του παιδιού."   }}

C++

Στο παρακάτω παράδειγμα στην γλώσσα προγραμματισμού C++ έχουμε το αντίστοιχο παράδειγμα δυναμικής αποστολής όπως στην Java παραπάνω. Η συνάρτηση virtual void print() στην κλάση Pateras έχει οριστεί ως υπερβατική συνάρτηση (Αγγλικά: virtual function). Η επιλογή της κλήσης void print() επιλέγεται στο χρόνο εκτέλεσης μέσω της δυναμικής αποστολής [7]:

#include <iostream>class Pateras {   public:      virtual void print() {          std::cout << "Κλήση του πατέρα. \n";      }};class Paidi : public Pateras {   public:      void print() {          std::cout << "Κλήση του παιδιού. \n";      }};int main() {   Pateras *oPateras = new Pateras();    // αντικείμενο της κλάσης Pateras   Paidi *toPaidi = new Paidi();         // αντικείμενο της κλάσης Paidi   Pateras *EnaAntikeimeno;              // Ορισμός ενός αντικειμένου της κλάσης Pateras   EnaAntikeimeno = oPateras;            // Το EnaAntikeimeno είναι μια αναφορά στο αντικείμενο oPateras   EnaAntikeimeno -> print();            // Τυπώνει: "Κλήση του πατέρα."   EnaAntikeimeno = toPaidi;   EnaAntikeimeno -> print();            // Τυπώνει: "Κλήση του παιδιού."   delete oPateras, toPaidi;   return 0;}

Παραπομπές