Φωτογραφία Κωνσταντίνος Κανελλόπουλος
Πρόσβαση σε νέες μεταβλητές παράγωγης κλάσης με setter
από Κωνσταντίνος Κανελλόπουλος - Tuesday, 13 December 2011, 1:12 PM
 
Κάτι περίεργο που δεν έχω καταφέρει να εξηγήσω κάνοντας την άσκηση.
Σε μια παράγωγη κλάση, όπως η Pclass όταν δημιουργώ νέο αντικείμενο E3 με τον default constructor και ορίζω με setter τις μεταβλητές, το eclipse μου χτυπάει όταν πάω να ορίσω τη νέα μεταβλητή X με την setX (η οποία δεν υπάρχει στην Βασική και υπάρχει στην παράγωγη). Μου επέβαλε για να το δεχτεί μία περίεργη σύνταξη που δεν την έχουμε δει :((Pclass)E3).setSalary(X) (add cast to E3)
Εναλλακτικά μου πρότεινε να βάλω στην βασική την setSalary (ως αφηρημένη ?) μέθοδο την οποία να υπερκαλύψω στην Pclass. Αλλά αυτό δεν έχει νόημα.
Μου έχει ξεφύγει κάτι;
 
Φωτογραφία ιορδάνης ασλανίδης
Re: Πρόσβαση σε νέες μεταβλητές παράγωγης κλάσης με setter
από ιορδάνης ασλανίδης - Tuesday, 13 December 2011, 2:40 PM
 
Αν έχω καταλάβει καλά, εφόσον η αναφορά σου είναι στην κλάση βάσης μπορείς να καλέσεις μόνο μεθόδους της παράγωγης κλάσης που επικαλύπτουν τις αντίστοιχες της κλάσης βάσης (ελπίζω να βγάζει νόημα αυτό που λέω). Επομένως όταν μία μέθοδος δηλώνεται μόνο στην παράγωγη κλάση τότε μπορεί να κληθεί είτε μέσω casting είτε εναλλακτικά να δηλωθεί και στην κλάση βάσης και μετά να επικαλυφθεί.
Φωτογραφία Νικόλαος Πανάγος
Απάντηση: Re: Πρόσβαση σε νέες μεταβλητές παράγωγης κλάσης με setter
από Νικόλαος Πανάγος - Tuesday, 13 December 2011, 3:38 PM
 
Ισχύει αυτό που λέει ο Ιορδάνης και που το έχει καταλάβει πολύ σωστά. Για την επίτευξη πολυμορφικής συμπεριφοράς, ένα από τα συστατικά είναι οι υπερκαλυπτόμενες μέθοδοι.
Η setSalary() που δεν είναι μια τέτοια δε μπορεί να κληθεί μέσω της αναφοράς κλάσης βάσης, εκτός αν κάνεις cast. Γι αυτό συνήθως κατά τη δημιουργία αντικειμένων στα οποία θέλουμε να αναφερόμαστε μέσω αναφοράς κλάσης βάσης χρησιμοποιούμε τον constructor που δημιουργεί και παράλληλα αρχικοποιεί.

Φωτογραφία Κωνσταντίνος Κανελλόπουλος
Απάντηση: Re: Πρόσβαση σε νέες μεταβλητές παράγωγης κλάσης με setter
από Κωνσταντίνος Κανελλόπουλος - Tuesday, 13 December 2011, 5:22 PM
 
Ευχαριστώ Ιορδάνη και Νίκο για τις απαντήσεις. Κατανοητό, αλλά τώρα μου δημιουργούνται κι άλλες απορίες:
1)Σχετικά με το casting, είναι αυτό που μαθαμε στην ενότητα 2 για αλλαγή τύπου μεταβλητών; Εφαρμόζεται και στα αντικείμενα; Το περίεργο είναι ότι ενώ το αντικείμενο το έχω δημιουργήσει ως HourlyEmployee
HE3=new salaries.HourlyEmployee();
πρέπει να κάνω casting για να αλλάξει τύπο(?)
((HourlyEmployee) HE3).setHours(50);

Αυτή η επιλογή θεωρείται πηγή bugs όπως μάθαμε στην ενότητα 2;

2)Υπάρχει άλλος τρόπος να αρχικοποιηθεί το αντικείμενο με την μέθοδο setter που δεν υπερκαλύπτει μέθοδο της βασικής κλάσης εκτός από casting; Με άλλα λόγια η setter χρειάζεται για την μεταβλητή Salary;
Φωτογραφία Νικόλαος Πανάγος
Απάντηση: Re: Πρόσβαση σε νέες μεταβλητές παράγωγης κλάσης με setter
από Νικόλαος Πανάγος - Tuesday, 13 December 2011, 7:04 PM
 
Εύλογες ερωτήσεις Κωστή και χαίρομαι που τις κάνεις.
Το casting γενικά θεωρείται κακό γιατί έχουμε αμεση μετατροπή ενός τύπου σε έναν άλλον. Είναι επικίνδυνο να το χρησιμοποιούμε διαρκώς αλλά σε κάποιες περιπτώσεις είναι χρήσιμο, αρκεί να ξέρουμε τι κάνουμε!
Εγώ θα σας προτείνω να το αποφεύγετε όπως γράφω και στις σημειώσεις, γιατί μπορούμε να πετύχουμε το επιθυμητο αποτέλεσμα χωρίς casting.

Πρώτη περίπτωση, να αρχικοποιήσεις το αντικείμενο παράγωγης κλάσης με τον constructor που αρχικοποιεί το αντικείμενο και να το 'αποθηκεύσεις' σε μία αναφορά κλάσης βάσης, π.χ.:

BaseClass r = new ChildClass(arg1, arg2, arg3, ...);

Δεύτερη περίπτωση, να το 'αποθηκεύσεις' σε μία αναφορά παράγωγης κλάσης, να το αρχικοποιήσεις μέσω αυτής της αναφοράς και μετά να το αποθηκεύσεις σε μία αναφορά κλάσης βάσης:

ChildClass r1 = new ChildClass();
r1.setSalary(1300);
....
BaseClass r2 = r1;

Προσωπικά προτιμώ τον 1ο τρόπο.