nik324 Δημοσ. 5 Δεκεμβρίου 2013 Δημοσ. 5 Δεκεμβρίου 2013 Γιατι στον παρακατω κωδικα θα τυπωθει το 2 και οχι το 1; class A{ int foo(){ return 1; } } class B extend A{ int foo(){ return 2; } } class C extend B { int bar (A a){ return a.foo(); } } class Test{ public static void main( String [] args){ C x = new C(); System.out.println( x.bar(x) ); } }
albNik Δημοσ. 5 Δεκεμβρίου 2013 Δημοσ. 5 Δεκεμβρίου 2013 Διοτι η B και C εχουν override foo=2. H foo() της C ( = B ) καλειται στην bar. Αυτο κανει το Runtime-Type-Identification.
albNik Δημοσ. 5 Δεκεμβρίου 2013 Δημοσ. 5 Δεκεμβρίου 2013 Ειναι η κεντρική ιδεα του πολυμορφισμού H bar γενικα δεχεται τύπου Α. Ομως και τα B,C ειναι τύπου Α , αρα έχουν δικαίωμα να κληθει η foo τους. Εχεις μια συναστηση που δεχεται object void Test(object o) { System.out.println(o.toString()); } Εσύ μπορεις να την καλέσεις με οποιαδήποτε κλαση (όλες ειναι object !!!) Αν καποια κλάση κανει override την toString() τότε θα εκτυπωθει αυτό, και οχι η object.toString().
defacer Δημοσ. 6 Δεκεμβρίου 2013 Δημοσ. 6 Δεκεμβρίου 2013 Γιατι στον παρακατω κωδικα θα τυπωθει το 2 και οχι το 1; Επειδή όλες οι methods είναι εξ' ορισμού virtual στη Java, θα κληθεί κάθε φορά η υλοποίηση της πιό εξειδικευμένης κλάσης που έχει το αντικείμενο. Στο παράδειγμά σου, το αντικείμενο το οποίο περνάς στη bar είναι τύπου C, το οποίο έχει ως πιο εξειδικευμένη υλοποίησης της foo αυτήν που δίνει η class B. Το γεγονός ότι η bar δηλώνει πως δέχεται ένα όρισμα τύπου A δεν παίζει ρόλο (πέραν του ότι ο compiler σε υποχρεώνει να σεβαστείς αυτή την απαίτηση), γιατί όταν μιλάμε για virtual methods δεν παίζει σημασία ο λεγόμενος static type του αντικειμένου (ως τι δηλαδή έχει δηλωθεί στον κώδικα η μεταβλητή που αναφέρεται σ' αυτό) αλλά ο runtime type (το τι είναι στην πράξη). Αν δεν είναι κατανοητό: A a1 = new A(); // static type A, runtime type A, καλείται η A.foo A a2 = new C(); // static type A, runtime type C, καλείται η B.foo C c = new C(); // static type C, runtime type C, καλείται η B.foo Προφανώς ο runtime type κάποιας μεταβλητής μπορεί να είναι το ίδιο ή περισσότερο εξειδικευμένος από το static type, ενώ το αντίθετο δε γίνεται (δεν το επιτρέπει ο compiler).
παπι Δημοσ. 6 Δεκεμβρίου 2013 Δημοσ. 6 Δεκεμβρίου 2013 Δες το σα ενα πιο ετσι overload. πχ ενα νορμαλ overload void foo(int); void foo(float); αν βαλεις στη foo int τοτε θα καλεσεις την πρωτη, αν βαλεις float τοτε θα καλεσεις την δευτερη. στο override το καλεσμα δεν εξραταται απο τα args αλλα απο τα object πχ BaseClass a = new DClass1; BaseClass b = new DClass2; a.foo() b.foo() το πρωτο θα καλεσει την foo της DClass1 και το δευτερο θα καλεσει την foo της DClass2
defacer Δημοσ. 6 Δεκεμβρίου 2013 Δημοσ. 6 Δεκεμβρίου 2013 Αυτό που λες παπί είναι λίγο μπερδευτικό, γιατί void foo(A x); // #1 void foo(C x); // #2 A c = new C(); foo(c); // καλεί την #1 Νομίζω καλύτερα να μη συγχέονται οι έννοιες εφόσον dynamic dispatch παραδοσιακά υποστηρίζεται μόνο στο this και όχι σε όλα τα υπόλοιπα arguments μιας method.
παπι Δημοσ. 6 Δεκεμβρίου 2013 Δημοσ. 6 Δεκεμβρίου 2013 Συσχετισμος ηταν. Πως εχουμε τα overload που εξαρτιουνται απο τα args, ετσι εχουμε τα overrides που εξαρτιουνται απο το object.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα