Dec 28, 2013

დელეგატები (1/5) - შესავალი


მიუხედავად იმისა, რომ ჩემი წინა პოსტები C# შეიცავდა დელეგატის გამოყენების ინსტრუქციებს, ახლა გადავწყვიტე ის რაც შეიძლება ზოგმა არ იცოდეს ავხსნა და ამით უფრო გასაგები გავხადო ჩემს მიერ დაწერილი წინა პოსტები, რომლებიც იყენებდნენ დელეგატებს, როგორც მეორეხარისხოვან ობიექტებს. ერთი სიტყვით, ეს პოსტი არის დასაწყისი დელეგატების და შევეცდები რაც შეიძლება ღრმად მოვიცვა ისინი.

დელეგატების გამოყენება მაშინ ხდება საჭირო, როდესაც გვსურს მეთოდის სხვა მეთოდისათვის გადაცემა. უკეთ გასაგებად ვნახოთ ქვემოთ მოცემული ფრაგმენტი კოდიდან:
Int i = int.Parse(“2013”);
ზემოთ მოცემულ კოდში არაფერია უჩვეულო, რადგან პროგრამირების ენის ათვისების დაწყებისთანავე ვსაზღვრავთ მეთოდებს, კოდის მაქსიმალურად შესაკუმშად და მათში ვაგზავნით არგუმენტს (ებს), ისე რომ ამაზე არც ვფიქრობთ. ამ ყველაფრის შემდეგ შესაძლებელი ხდება მეთოდის არგუმენტი გახდეს სხვა მეთოდი, რაც თავდაპირველად ცოტა უჩვეულოდ შეიძლება მოგეჩვენოთ, მაგრამ არაფერია.
C ში და C++ შესაძლებელია უბრალოდ ფუნქციის (იგივე მეთოდი) მისამართის აღება და მისი უბრალოდ მეორე ფუნქციის არგუმენტად გატარება. აღსანიშნავია, რომ C ში არ არსებობს ტიპობრივი უსაფრთხოება. შესაძლებელია ნებისმიერი ფუნქციის გატარება მისამართით სადაც პოინტერიანი (pointer) პარამეტრია მითითებული. სამწუხაროდ ეს პრაქტიკა არც ისე უსაფრთხოა და ბევრ პრობლემას იწვევს. ამიტომ არის, რომ .NET გარემო ამის საშუალებას არ იძლევა, უფრო სწორედ არ რთავს მომხმარებელს ამის გაკეთების ნებას. თუ გსურთ, რომ მეთოდი გაატაროთ როგორც არგუმენტად საჭირო ხდება მეთოდის დეტალების მითითება ახალი ტიპისთვის - დელეგატისთვის. მარტივად რომ ვთქვათ, დელეგატები განსაკუთრებული ტიპის ობიექტებია. განსაკუთრებული იმ მხრივ, რომ აქამდე რა ტიპის ობიექტიც არ უნდა შეგექმნათ ის შეიცავდა ინფორმაციას, ხოლო დელეგატი არ შეიცავს მეთოდის (ების) მისამართს (ებს).
C# ში კლასის განსასაზღვრად საჭიროა ორი ნაბიჯი. სასურველი კლასის განსაზღვრა და ამ კლასის ობიექტის შექმნა შიდა წევრებთან წვდომისთვის,  თუ რა თქმა უნდა კლასი არ არის სტატიკური. დელეგატების შემთხვევაშიც იმავე პროცესის გამეორებაა საჭირო. პირველ რიგში საჭიროა დელეგატის განსაზღვრა, რაც იმას ნიშნავს, რომ კომპილატორს მიუთითოთ რა ტიპის მეთოდი უნდა წარმოადგინოს დელეგატმა. ამის შედეგ საჭიროა ამ დელეგატის ერთი ან ორი ინსტანციის შექმნა. სცენას მიღმა კი კომპილატორი ქმნის კლასს, რომელიც წარმოადგენს დელეგატს. ქვემოთ მოცემულია დელეგატის განსაზღვრის სინტაქსი:
delegate void doubleMethodInvoker(double x);  
ამ შემთხვევაში განვსაზღვრე დელეგატი სახელად doubleMethodInvoker. როგორც აღვნიშნე, ამ დელეგატს შეუძლია იმ მეთოდების მისამართის გამოყენება, რომელის დაბრუნების ტიპია void და იღებს double ტიპის ერთ პარამეტრს. მთავარი აზრი იმისა, თუ რატომ ვიყენებთ დელეგატს და არა C++ სავით pointer ებს, მდგომარეობს იმაში, რომ დელეგატები ტიპობრივად უსაფრთხოა. რაც იმას ნიშნავს, რომ დელეგატის განსაზღვრისას ხდება გამოსაძახებელი მეთოდის მაქსიმალურად დაწვრილებით აღწერა (დაბრუნების ტიპი, პარამეტრების ტიპები და ოდენობა...).
მაგალითისთვის ვნახოთ კიდევ ერთი კოდის ფრაგმენტი, სადაც ვსაზღვრავ ერთ დელეგატს, რომელიც პარამეტრად იღებს ორ double ტიპის პარამეტრს და აბრუნებს string ტიპის მნიშვნელობას.
Delegate string twoDoubleOps(double F, double S);
დელეგატის განსაზღვრის სინტაქსი ერთის მხრივ მეთოდის განსაზღვრის სინტაქსს ჰგავს, იმ გამონაკლისებით, რომ წინ საჭიროა delegate საკვანძო სიტყვის გამოყენება და ეს „მეთოდის“ აღწერა არ შეიცავს მეთოდის ტანს. დელეგატის განსაზღვრა რადგან ჰგავს კლასის განსაზღვრას და სინამდვილეში ტექნიკურად ეს ასეც არის, მისი განსაზღვრა შესაძლებელია ნებისმიერ ადგილას, სადაც დასაშვებია კლასის გამოყენება. ასევე დელეგატს შეიძლება დაენიშნოს წვდომის ნებისმიერი მოდიფიკატორი: public, private, protected და ასე შემდეგ.
შემდეგ პოსტში უკვე დელეგატებს გამოვიყენებ, ხოლო მოგვიანებით რამდენიმე კერძო მაგალითს განვიხილავ.

No comments:

Post a Comment