User Tools

Site Tools


java:polymorphism

Στατικός και Δυναμικός Πολυμορφισμός

Στατικός Πολυμορφισμός (a.k.a. Υπερφόρτωση Μεθόδων)

Κατά την εισαγωγή στις μεθόδους της κλάσης είδαμε την δυνατότητα ορισμού σε μία κλάση μεθόδων με το ίδιο όνομα αλλά με διαφορετικό αριθμό ή/και τύπους παραμέτρων. Η δυνατότητα αυτή που μας δίνει η Java και ο Αντικειμενοστραφής Προγραμματισμός γενικότερα, ονομάζεται method overloading και οφείλεται στο γεγονός ότι μία μέθοδος δεν ορίζεται μόνο από το όνομα της αλλά και από το σύνολο των τυπικών παραμέτρων της. Τυπικές παράμετροι και όνομα αποτελούν την υπογραφή (signature) της κάθε μεθόδου.

Ένα παράδειγμα method overloading δίνεται παρακάτω:

Calculation.java
class Calculation {  
  void sum(int a,int b){ System.out.println(a+b); }
  void sum(double a, double b) { System.out.println(a+b); }
  void sum(int a,int b,int c){ System.out.println(a+b+c); }  
 
  public static void main(String args[]) {  
    Calculation obj=new Calculation();  
    obj.sum(10,10,10);  
    obj.sum(20,20);
    obj.sum(12.2, 11.3);    
  }
}

Η παραπάνω δυνατότητα αναφέρεται συχνά και ως στατικός πολυμορφισμός (static polymorphism) σε αντιδιαστολή με τον δυναμικό πολυμορφισμό που θα δούμε στη συνέχεια.

Όπως προαναφέραμε, ο στατικός πολυμορφισμός βασίζεται στον διαφορετικό αριθμό, τον τύπο και τη σειρά ορισμάτων. Το συγκεκριμένο είδος πολυμορφισμού ονομάζεται στατικό διότι η μέθοδος που θα κληθεί αποφασίζεται από τον compiler κατά την μεταγλώττιση του προγράμματος.

Δυναμικός Πολυμορφισμός

Ας υποθέσουμε δύο κλάσεις που η μία κληρονομεί από την άλλη και οι δύο έχουν δύο διακριτές μεθόδους με το ίδιο όνομα και τις ίδιες τυπικές παραμέτρους, δηλαδή το ίδιο signature. Σε αυτή την περίπτωση λέμε ότι η μέθοδος της υποκλάσης, επανα-ορίζει (overrides) την μέθοδο της γονικής της κλάσης. Ένα παράδειγμα είναι το παρακάτω.

Polymorphism.java
class Animal {
 
  public void signature(){
    System.out.println("I am an animal.");
  }
}
 
class Mammal extends Animal {
  int numberOfBabies;
 
  public Mammal(int babies) {
    numberOfBabies = babies;
  }
 
  public int getBabies() {
    return numberOfBabies;
  }
 
  public void signature() {
    System.out.println("I am a mammal! I birth "+numberOfBabies+" babies.");
  }
}
 
class Dog extends Mammal {
  private String name;
 
  public Dog(int babies, String name) {
    super(babies);
    this.name = name;
  }
 
  public String getName() {
    return name;
  }
 
  public void signature() {
    System.out.println("I am a dog! My name is "+name+".");
  }
}
 
public class Polymorphism {
 
  public static void main(String args[]) {
    Animal animal = new Animal(); // Animal reference and object
    Animal mammal = new Mammal(3);  // Animal reference but Mammal object
    Animal dog = new Dog(4, "Azor");    // Animal reference but Dog object
 
    animal.signature(); //output: I am an animal.
    mammal.signature(); //output: I am a mammal!
    dog.signature(); //output: I am a dog!
 
    //mammal.getBabies();
    //dog.getName();
  }
}

Παρατηρούμε ότι η κλήση της μεθόδου signature από τρεις μεταβλητές τύπου Animal που η πρώτη (a) δείχνει σε αντικείμενο της γονικής κλάσης (Animal), η δεύτερη (b) σε αντικείμενο της υποκλάσης (Mammal) και η τρίτη η δεύτερη (b) σε αντικείμενο της υποκλάσης (Dog) έχει ως αποτέλεσμα την κλήση διαφορετικών μεθόδων. Η απόφαση για το ποια μέθοδος θα κληθεί σε κάθε μία από τις τρεις περιπτώσεις δεν μπορεί να αποφασιστεί κατά την μεταγλώττιση του προγράμματος. Το JVM καλείται να αποφασίσει, με βάση τον τύπο του αντικειμένου στο οποίο δείχνει κάθε μεταβλητή κατά την εκτέλεση.

Στο παραπάνω παράδειγμα, το JVM γνωρίζει το είδος του αντικειμένου στο οποίο δείχνουν οι μεταβλητές a, b και c ανεξάρτητα εάν η reference μεταβλητή είναι του τύπου της γονικής κλάσης ή της υποκλάσης. Η παραπάνω διάκριση είναι γνωστή ως δυναμικός πολυμορφισμός (dynamic polymorphism), διότι το ποια μέθοδος θα κληθεί αποφασίζεται κατά την εκτέλεση και όχι κατά την μεταγλώττιση.

java/polymorphism.txt · Last modified: 2020/03/27 13:18 by gthanos