Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

ΑΝΤΙΚΕΙΜΕΝΟ ΚΛΩΝΟΣ???

Îåêßíçóå áðü ôï ìÝëïò vtops. Τελευταία δημοσίευση από το μέλος Μπιρμπίλης Γεώργιος στις 14-05-2009, 23:06. Υπάρχουν 5 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  08-05-2009, 19:09 50572

    ΑΝΤΙΚΕΙΜΕΝΟ ΚΛΩΝΟΣ???

    Καλησπέρα σε όλους

    Έστω ότι έχω ένα TextBox σε μια φόρμα (txt1)

    Και εκτελώ τις ακόουθες εντολές:

    TextBox txt2=this.txt;

    txt1.text="hello";

    Γιατί και το txt2 παίρνει το Text "hello" και πως μπορεί να αποφευχθεί;

     

    Ευχαριστώ πολυ!


    Best Regards
  •  08-05-2009, 19:58 50575 σε απάντηση της 50572

    Απ: ΑΝΤΙΚΕΙΜΕΝΟ ΚΛΩΝΟΣ???

    Υποθέτω ότι όταν γράφεις TextBox txt2=this.txt εννοείς στην πραγματικότητα this.txt1;

    Αυτό που συμβαίνει είναι απόλυτα λογικό γιατί μόλις έθεσες στην μεταβλητή txt2 το αντικείμενο txt1. Η txt2 δεν είναι κλώνος του txt1, είναι το ίδιο το txt1.

    Υποψιάζομαι ότι στο παρελθόν έχεις δουλέψει με VB6 όπου υπήρχε το "feature" (και πηγή πολλαπλών bug) να σου επιστρέφει το κείμενο ενός TextBox ακόμα και αν δεν καλούσες ρητα την txt1.Text. Αυτό το "feature" ευτυχώς καταργήθηκε αλλά ακόμα και να υπήρχε, σκέψου τί έγραψες. Έχεις μία μεταβλητή τύπου TextBox την οποία γεμίζεις με ένα άλλο TextBox. Ακόμα και στη VB6 θα θεωρούσες ότι σε ενδιαφέρει το control και όχι το κείμενο.

     


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  11-05-2009, 17:41 50646 σε απάντηση της 50575

    Απ: ΑΝΤΙΚΕΙΜΕΝΟ ΚΛΩΝΟΣ???

    Και αν ψάξουμε λίγο βαθύτερα, έχοντας λίγη γνώση από C++, θα δούμε το εξής:

    Το TextBox είναι ένα class, και η γραμμή

       TextBox txt1 = new TextBox();

    μεταφράζεται "by default" από to CLR ως "όρισε ένα καινούριο pointer σε αντικείμενο τύπου TextBox. Το αντικείμενο txt2 θα είναι επίσης pointer, και όταν κάνεις assignment με τον operator = και έχεις αριστερά και δεξιά pointers, σημαίνει απλά ότι θα χρησιμοποιήσεις μία θέση μνήμης για το αντικείμενο και θα έχεις δύο παλικάρια (pointers) να δείχνουν στο αντικείμενο αυτό.

    Όντως η VisualBasic είχε default property για ορισμένους τύπους σε κάποιες βιβλιοθήκες, η οποία καλείται γράφουμε μόνο το όνομα το αντικειμένου, χωρίς ".PropertyName". Όμορφο εκείνο τον καιρό, γιατί λιγόστευε τον κώδικα που έπρεπε να γράψει κανείς.

     

     


    Panagiotis Georgiadis
    HBM Netherlands B.V.
    www.twitter.com/HimWithCurls
  •  12-05-2009, 00:24 50658 σε απάντηση της 50646

    Απ: ΑΝΤΙΚΕΙΜΕΝΟ ΚΛΩΝΟΣ???

    Σας ευχαριστώ για την απάντηση παιδιά, αλλά δεν έχω καταλάβει πως μπορώ να αποφύγω αυτό το πρόβλημα.

    Για να γίνει ποιο κατανοητό τι θέλω να κάνω θα αναφέρω το παράδειγμα μου ξανά με περισσότερες λεπτομέρειες:

    Έστω ότι έχω το textbox txt1

    και εκτελω:

    TextBox txt2=this.txt1;

    /* Εδώ μεσολαβούν εντολές που αλλάζουν αρκετά properties πάνω στο txt1

    και την στιγμή που τελειώνουν αυτές οι εντολές θέλω κάποια properties να τα επαναφέρω πίσω (από το backup που κράτησα στο txt2)

    Όμως από ότι φαίνεται το txt2 έχει γίνει όπως και το txt1*/

    Πως λοιπόν μπορώ να φτιάξω ένα ίδιο αντικείμενο 2 , που όταν πειράξω properties του αντικειμένου  1 να μην πειραχτούν τα properties του αντικειμένου 2;

    Ευχαριστώ πολύ.


    Best Regards
  •  12-05-2009, 00:44 50662 σε απάντηση της 50658

    Απ: ΑΝΤΙΚΕΙΜΕΝΟ ΚΛΩΝΟΣ???

    Δεν υπάρχει πρόβλημα στον κώδικα, αλλά στην κατανόηση του τί είναι μεταβλητή και αντικείμενο. Η txt1 είναι μεταβλητή που δείχνει σε ένα αντικείμενο. Η txt2 είναι μεταβλητή η οποία δείχνει στο ίδιο αντικείμενο με την txt1. Το txt2 δεν "έγινε" όπως και το txt1, είναι το txt1 και πάντα ήταν το txt1. 

    Όσον αφορά τώρα την επαναφορά κάποιων properties, θα πρέπει να τις αποθηκεύσεις σε κάποιες μεταβλητές και να επαναφέρεις τις τιμές τους στο τέλος. Ακόμα και αν η κλάση TextBox είχε κάποια μέθοδο Clone, δεν θα έπρεπε να τη χρησιμοποιήσεις γιατί ένα textbox είναι σχετικά βαρύ αντικείμενο. Το να δημιουργήσεις ένα αντίγραφο του μόνο και μόνο για να επαναφέρεις κάποια properties είναι σπατάλη resources.

     


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  14-05-2009, 23:06 50712 σε απάντηση της 50658

    Απ: ΑΝΤΙΚΕΙΜΕΝΟ ΚΛΩΝΟΣ???

    Πρέπει να κάνεις

    TextBox txt2 = New TextBox();

    txt2.Text = txt1.Text;

    κάνοντας TextBox txt2 ορίζεις μια τοπική μεταβλητή txt2 τύπου TextBox που (δεν) περιέχει τίποτε (=null [ή nil στην Pascal])

    Με τη New TextBox φτιάχνεις ένα νέο TextBox object (new TextBox class instance) και καλείς τον default/parameterless constructor της αυτόματα για να την αρχικοποιήσει (αν έχει οριστεί κάποιος parameterless constructor - σε κάποιες γλώσσες ορίζεις προεραιτικά) και αναθέτεις το object αυτό στην txt2 (που είναι τύπου reference σε TextBox)

    Μετά θέτεις στην ιδιότητα Text του αντικειμένου που δείχνει η txt2 την τιμή της ιδιότητας Text του αντικειμένου που δείχνει η txt1. Συνήθως αυτή είναι τύπου String και οι περισσότερες γλώσσες το υλοποιούν εδώ και κάμποσα χρόνια ως ένα immutable object που δείχνει σε ένα string pool, οπότε αν πειραχθεί το txt1.Text στο μέλλον απλά θα δείχνει αλλού και δεν θα επηρεάσει την txt2.Text που συνεχίζει να δείχνει στο παλιό string στην string pool.

    Αν η Text είναι ένα reference σε αντικείμενο άλλου τύπου από String και πεις txt1.Text.doSomething() τότε η doSomething() μέθοδος του txt1.Text μπορεί εν δυνάμει (αν προκαλεί side-effects) να επηρεάσει την txt2.Text (αφού δείχνουν στο ίδιο αντικείμενο).

    Αν η Text ήταν αριθμός ή άλλο boxed native type του .NET (π.χ. char) τότε απλά στην ανάθεση γίνεται κόπια της τιμής και το txt1.Text δεν σχετίζεται πλέον με το txt2.Text

    ----

    Αν πείς txt2 = this.txt1 ή απλά txt2 = txt1 (αφού το this εννοεί το τρέχον στιγμιότυπο/αντικείμενο της κλάσης όπου εκτελείται ο παραπάνω κώδικας και το this.txt1 εννοεί δώσε μου το public πεδίο ή property "txt1" του αντικειμένου [π.χ. της φόρμας]), τότε βάζεις τη μεταβλητή txt2 (τύπου TextBox) να δείχνει εκεί που δείχνει η μεταβλητή txt1 (ομοίως τύπου TextBox), δηλαδή να δείχνουν στο ίδιο αντικείμενο (aliasing δηλαδή). Υπόψη ότι οι μεταβλητές που κρατάνε αντικείμενα είναι απλά δείκτες (τα "κρατάνε ζωντανά" για να μην τα σβήσει από τη μνήμη ο garbage collector - αν κανείς δείκτης δεν δείχνει στο αντικείμενο, τότε θα το "αρπάξει" το GC [στο COM αντίστοιχα όταν του έλεγες να κάνει Release και το refcount έπεφτε σε 0 το αντικείμενο - συνήθως - σχεδιαζόταν να αυτοκαταστρέφεται]).

    Τα object references δεν είναι records/structs (έχει και τέτοια το .NET αν τα χρειάζεσαι, καλό είναι να αποφεύγονται όμως εκτός από ειδικές περιπτώσεις, π.χ. όταν μιλάς με το Win32 ή άλλα μη αντικειμενοστραφή API), αλλά μοιάζουν με τους pointers της C++ (είναι μάλλον managed [εννοεί πως γίνεται διαχείριση του lifetime του σχετικού resource] typed pointers στην ορολογία της Object Pascal)

     ----

    ελπίζω να μην σε κούρασα πολύ και να σου άνοιξα την όρεξη να διερευνήσεις το θέμα (δες το δωρεάν βιβλίο Thinking in Java του Bruce Eckel στο www.eckelobjects.com [ίσως έχει παύλα μεταξύ eckel και objects, δεν θυμάμαι])

    Microsoft MVP J# 2004-2010
    Borland Spirit of Delphi 2001
    http://zoomicon.com
    Δημοσίευση στην κατηγορία:
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems