java:generics_inheritance

Κληρονομικότητα παραμετρικών τύπων δεδομένων

public void boxTest(Box<Number> n) { /* ... */ }  //line 1
 
Box<Number> box = new Box<Number>();  //line 3
box.add(new Integer(10));             //line 4
box.add(new Double(10.1));            //line 5
 
Box<Double> doubleBox = new Box<Double>(); // line 7
doubleBox.add(new Double(10.1));           // line 8
 
box.boxTest(doubleBox); // μπορούμε να γράψουμε?

Ο παραπάνω κώδικας είναι σωστός στις γραμμές 3-5 διότι οι κλάσεις Integer και Double είναι υποκλάσεις της κλάσης Number. Δεν ισχύει όμως το ίδιο για την γραμμή 8 καθώς η κλάση Box<Double> δεν είναι υποκλάση της κλάσης Box<Number>, όπως δείχνει το παρακάτω σχήμα. Box<Number> και Box<Double> είναι υποκλάσεις της κλάσης Object.

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

Οι σχέσεις κληρονομικότητας μεταξύ παραμετρικών τύπων μπορούν να οριστούν ως εξής. Αν ένα παραμετρικό interface κληρονομεί ένα άλλο παραμετρικό interface τότε μπορούμε να πούμε ότι τα δύο interfaces διατηρούν την σχέση κληρονομικότητας ΜΟΝΟ αν ο παραμετρικός τύπος που χρησιμοποιούν είναι κοινός. Για παράδειγμα, η παρακάτω παραμετρική σχέση υποδηλώνει κληρονομικότητα ΜΟΝΟ για παραμέτρους ιδίου τύπου

  Collection<E>                Collection<String>                Collection<Number>
      |                               |                                Χ
      v          π.χ.                 v            όχι όμως και        v
    List<E>                       List<String>                      List<Integer>

Αντίστοιχα, αν μία παραμετρική κλάση κληρονομεί μία άλλη παραμετρική κλάση τότε μπορούμε να πούμε ότι οι δύο κλάσεις διατηρούν την σχέση κληρονομικότητας ΜΟΝΟ αν ο παραμετρικός τύπος που χρησιμοποιούν είναι κοινός. Δείτε το παρακάτω παράδειγμα

  HashSet<E>                HashSet<String>                   HashSet<Number>
      |                          |                                  Χ
      v          π.χ.            v             όχι όμως και         v
LinkedHashSet<E>         LinkedHashSet<String>               LinkedHashSet<Integer>

Τέλος, αν μία παραμετρική κλάση υλοποιεί ένα παραμετρικό interface τότε μπορούμε να πούμε ότι το interface και η κλάση διατηρούν σχέση κληρονομικότητας ΜΟΝΟ αν ο παραμετρικός τύπος που χρησιμοποιούν είναι κοινός.

    List<E>                   List<String>                      List<Number>
      |           π.χ.             |           όχι όμως και         X
      v                            v                                V
  ArrayList<E>             ArrayList<String>                 ArrayList<Integer>
java/generics_inheritance.txt · Last modified: 2016/02/26 11:15 (external edit)