Jump to content
Sign in to follow this  
GHOST_FATHER

java სწავლა

Recommended Posts

სანამ ჯავაზე ვისაუბრებდი ჩამივარდა ხელში წიგნი რომელიც არის არაჩვეულებრივად აღწერილი , ამიტომაც ამ წიგნის მასალიდ "დაკოპირებას" ვაპირებ, ჩემდა სამწუხაროდ, ვორდის დოკუმენტს არ გააჩნია ავტორი თუ ვინ დაწერა ამიტომაც მომიტევოს ავტორმა რათა მის ინტელექტუალურ საკუთრებას ვისაკუთრებ, თუ ავტორი გამოჩნდება რათქმაუნდა ჩავასწორებ და დავწერ, არ მაქვს პრობლემა.

14ad7b4cb8f1.jpg

ობიექტზე ორიენტირებული დაპროგრამების საწყისები

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

პროგრამირების პარადიგმები

თავიდან, მანქანურ კოდებში დაწერილი უმარტივესი პროგ­რა­მებიც კი, შეადგენდნენ ძნელად გასაგები, ასობით სტრი­ქო­ნის­აგან შემდგარ ტექსტს. დაპროგრამების დაჩქა­რებისა და გამარტივების მიზნით შეიქმნა მაღალი დონის ალგორით­მული ენები: Fortran, Algol და ასობით სხვა. ამ ენების გამო­ყე­ნე­ბით მანქანური ბრძანებების (კოდის) შექ­მნის რუტინული ოპერაციების განხორციელება დაეკისრა კომპილატორებს. მაღალი დონის ენებზე დაწერილი იგივე პროგრამები გახდა გაცილებით გასაგები და მოკლე. კომპი­უ­ტერული სისტე­მების მკვეთრმა განვითარებამ გამო­იწ­ვია უფრო რთული ამოცანების გადაწყვეტის აუცი­ლებლობა, რა­მაც კვლავ მოახ­დინა პროგრამების ზომების მნიშვნელო­ვანი გაზრდა.

წარმოიქმნა იდეა: პროგრამა გაფორმდეს რამდენიმე, შეძლე­ბისდაგვარად მარტივი პროცედურის ან ფუნქციის სახით, რომლებიც გადაწყვეტენ თავის კონკრეტულ ამოცანას. მცირე ზომის პროცედურის დაწერა, კომპილაცია და გამართვა გაცილებით უფრო ადვილად და სწრაფად შეიძლება. შემდეგ საჭირო იქნება, მხოლოდ ყველა პროცედურის საჭირო მიმ­დევრობით, ერთ პროგრამად გაერთიანება. გარდა ამისა, ერთ­ხელ დაწერილი პროცედურები შეიძლება გამოყენე­ბუ­ლი იქნას სხვა პროგრამებში, როგორც „სამშენებლო აგურე­ბი“. პროცედურული პროგრამირება სწრაფად იქცა პარ­ა­დიგ­მად. ყველა მაღალი დონის ენაში მოხდა პროცედურებისა და ფუნქციების დაწერის საშუალებების ჩართვა. შეიქმნა სხვად­ასხვა საგნობრივი სფეროსათვის პროცედურებისა და ფუნქ­ცი­ების უამრავი ბიბლიოთეკა.

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

მოდულურობა;

კითხვადობა;

პროგრამის შესრულების სტანდარტული მართვის სქემები;

დოკუმენტირება;

ტესტების შედგენა პროგრამის დამუშავების ადრეულ ეტაპზე.

პროგრამისტების წინაშე მდგარი ამოცანების სირთულემ აქაც იჩინა თავი: დიდი პროგრამა შედგებოდა ასობით პრო­ცედურისაგან და იგი კვლავ გახდა ძნელად გასააზრებელი და გასამართი. აუცილებელი გახდა პროგრამირების ახალი სტილის შემუშავება.

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

მოდულების ერთმანეთის მიმართ მაქსიმალური ავტონომი­უ­რობის უზრუნველსაყოფად, საჭიროა მკაფიოდ გამოიყოს ის პროცედურები, რომლის გამოძახებაც შესაძლებელია სხვა მოდულებისგან - ანუ ღია (Public) პროცედურები, და დამ­ხმარე პროცედურები, რომლებიც ამუშავებენ ამ მოდულში მოთავსებულ მონაცემებს - ანუ დახურული (Private პრივა­ტული) პროცედურები. პირველი ტიპის პროცედურები ჩა­მოთ­ვლილია მოდულის ცალკე ნაწილში - ინტერფეისში (interface), მეორე ტიპის მონაწილეობენ მხოლოდ მოდულის რეალიზაციაში (implementation). მოდულში აღწერილი ცვლა­დებიც იყოფა ღიად (მითითებული ინტერფეისში და სხვა მოდულებიდან წვდომადი) და დახურულად (მათზე წვდომა შესაძლებელია მხოლოდ იმავე მოდულში შემავალი პროცედურებისაგან). პროგრამირების სხვადასხვა ენებში ეს დაყოფა სხვადსხვანაირად ხდება. Turbo Pascal-ში მოდული სპეციალურად იყოფა ინტერფეისად და რეალიზაციად. ალგორითმულ ენა C-ში ინტერფეისი გატანილია „სათაო“ (header) ფაილში. ენა C++ -ში, ამის გარდა, ინტერფეისის აღწერისათვის შესაძლებელია აბსტრაქტული კლასების გა­მო­ყენება. Java-ში არსებობს ინტერფეისის აღწერის სპე­ციალური კონსტრუქცია, რომელსაც ასევე ეწოდება - interface, მაგრამ შესაძლებელია აბსტრაქტული კლასების შექმნაც.

ასე წარმოიშვა მონაცემებისა და მათი დამუშავების მეთო­დების დაფარვის, ინკაფსულაციის (incapsulation) იდეა. ინკაფსულაციის მიზანი არაა სხვა მოდულს დაუმალოს საჭირო კომპონენტი. მისი ორი მთავარი მიზანია: პირველი - უზრუნველყოს მოდულის გამოყენების უსაფრთხოება, ინ­ტერ­ფეისში გამოიტანოს და გახადოს საყოველთაოდ ხელმი­საწვდომი მხოლოდ ინფორმაციის დამუშავების ის მეთო­დები, რომლებსაც არ შეუძლიათ დააზიანოს ან წაშა­ლოს საწყისი მონაცემები; მეორე - შეამციროს სირთულე, გარე მოდულებისათვის რეალიზაციის წვრილმანი დეტალე­ბის დაფარვის გზით.

კვლავ წარმოიშვა ამოცანა, რა გზით მოხდეს პროგრამის დაყოფა მოდულებად. ამ შემთხვევაში უფრო მისაღები აღმოჩნდა პროგრამირების ძველი ამოცანების გადაწყვეტები - ბუნებრივი და ხელოვნური ობიექტების მოქმედებების მოდელირება (ადამიანების, ცხოველების, ტექნოლოგიური პროცესების მართვის სისტემების, პროგრამული მართვის ჩარხების და სხვა). მართლაც, ყოველი ობიექტი - ადამიანი, ავტომობილი, ტექნოლოგიური პროცესი, ხასიათდება გარ­კ­ვე­ული პარამეტრებით. მაგალითად, გვარი, წლოვანება, წონა, სიმაღლე, მაქსიმალური სიჩქარე, ტვირთამწეობა და სხვა. ობი­ექტი შეიძლება ასრულებდეს სხვადსხვა მოქმედებებს: გადაადგილდებოდეს სივრცეში, იზრდებოდეს ან მცირდე­ბოდეს, ჭამოს, სვას, შეიცვალოს თავისი პირვანდელი პარა­მეტრები. მოსახერხებელია ობიექტის მოდელირება მოხდეს მოდულის სახით. მისი პარამეტრები, მახასიათებლები იქნე­ბა საწყისი მონაცემები - მუდმივი ან ცვლადები, ხოლო მოქ­მედებები - პროცედურები.

მოსახერხებელი გამოდგა აგრეთვე საწინააღმდეგოც - პროგ­რამა ისე დაიყოს მოდულებად, რომ იგი გარდაიქმნას ურთი­ერთ­დაკავშირებულ ობიექტებად. ასე წარმოიშვა ობიექტზე ორიენტირებული დაპროგრამება (object-oriented program­ming - OOP), რომელიც პროგრამირების თანამედ­როვე პარადიგ­მას წარმოადგენს.

ობიექტზე ორიენტირებული დაპროგრამების იდეის წარმო­შობას სხვა წანამძღვრებიც გააჩნია. ცნობილია, რომ ყოველი კომპიუტერული პროგრამა შედგება ორი ელემენ­ტისაგან: კოდი (პროგრამის ტექსტის პროცედურული ნაწი­ლი) და მონაცემები. კონცეპტუალურად პროგრამა ორგანი­ზებული შეიძლება იყოს თავისი კოდის ან მონაცემების გარშემო. ანუ, ზოგიერთი პროგრამის ორგანიზება განისაზ­ღვრება იმით, თუ „რა ხდება“, ხოლო სხვების „რაზე ხდება მოქმედებები“. არსებობს პროგრამების შედგენის ორი კონ­ცეფცია. პირველ მიდგომას უწოდებენ პროცესზე ორიენტირებულ მოდელს. ასეთი მიდგომისას პროგრამა ესაა წრფივი ბიჯების მიმდევ­რობა (ე.ი. კოდი). პროცესზე ორიენტირებული მოდელი, შეიძლება განვიხი­ლოთ, როგორც მონაცემების დამმუშავე­ბე­ლი კოდი. ამ მო­დელს იყენებენ პროცედურული ენები მაგალითად C, Pascal და სხვა. თუმცა, ასეთი მიდგომა წარმოშობს სხვადასხვა პრობლემებს პროგრამის ზომისა და სირთულის ზრდასთან დაკავშირებით.

როგორც ზემოთ აღვნიშნეთ, სირთულის ზრდადი ხასიათის გადასალახად, დამუშავდა ობიექტზე ორიენტირებული მიდ­­გომა. ობიექტზე ორიენტირებული პროგრამირება ან­ხორ­ციელებს პროგრამის ორგანიზებას მისი მონაცემების (ანუ ობიექტების) გარშემო. ობიექტზე ორიენტირებული პროგ­რამირება ესაა მონაცემები, რომლებიც მართავენ კოდ­თან წვდომას.

ობიექტების სახით შეიძლება წარმოვადგინოთ სხვადასხვა ცნებები. მაგალითად, ფანჯარა დისპლეის ეკრანზე - ესაა ობიექტი, რომელსაც აქვს სიგანე width და სიმაღლე hight, ეკრანზე მდებარეობა, ჩვეულებრივ აღიწერება მარცხენა ზე­და კუთხის (x,y) კოორდინატებით, შრიფტი, რომლითაც ფანჯარაში ტექსტი გამოდის, მაგალითად Times New Roman, ფონის ფერი color და სხვა პარამეტრები. ფანჯარა ეკრანზე შეიძლება გადაადგილდებოდეს move() მეთოდით, გაეზარ­დოს ან შეუმცირდეს ზომები მეთოდით size(), გარკვეული რეაგირება მოახდინოს მაუსის დაჭერაზე და სხვა. ფაქტი­ურად ესაა სრულყოფილი ობიექტი. ღილაკები, ლიფტები და ფანჯრის სხვა ელემენტებიც ობიექტებს წარმოადგენენ, რომ­ლე­ბსაც თავის მხრივ აქვთ თავისი ზომები, შრიფტები, შეუძ­ლით გადადგილება.

ობიექტზე ორიენტირებული დაპროგრამების იდეა ძალიან ნაყოფიერი გამოდგა და იგი აქტიურად განვითარდა. აღმოჩ­ნდა, რომ უმჯობესია ამოცანა დაისვას მოქმედი ობიექტების ერთობლიობის სახით - ასე წარმოიშვა ობიექტზე ორიენ­ტირებული ანალიზი (OOA, object-oriented Analysis). შესაძ­ლე­ბელი გახდა რთული სისტემების დაპროექტება ობიექ­ტების სახით - წარმოიშვა ობიექზე ორიენტირებული დაპ­როექტება (OOD, object-oriented design).

ობიექტზე ორიენტირებული დაპროგრამება უკვე 20 წელია ვითარდება. არსებობს რამდენიმე სკოლა, რომლებიც თავი­სებურად აყალიბებენ ძირითად პრონციპებს და ობიექ­ტებთან მუშაობის თავის პრინციპების ერთობლიობას გვთა­ვაზობენ.

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

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

აბსტრაქციის გამოყენების მძლავრ იარაღს წარმოადგენს იერარ­ქიული კლასიფიკაციები. ის საშუალებას იძლევა გავ­ა­მარტივოთ რთული სისტემების სემანტიკა (შინაარსი), მათი ფრაგმენტებად დაყოფის გზით, რომლებიც სამართავადაც უფრო ადვილი იქნება. მაგალითად, გარეგნულად ავტომო­ბილი ერთ ობიექტად აღიქმება. მაგრამ თუ შიგ ჩავიხედავთ, ვნახავთ, რომ იგი შედგება რამდენიმე ქვესისტემისაგან: საჭის მართვის სისტემა, მუხრუჭები, აუდი­ოსისტემა, გამათ­ბობელი და სხვა, თითოეული ეს ქვესისტემა აგებულია უფ­რო სპეციფიური კვანძებისაგან. მაგა­ლითად, აუდიო­სის­ტემა შედგება რადიომიმღებისაგან, კომპაქტ დისკებისა და/ან აუდიო კასეტების დამკვრე­ლისაგან. ამ მაგალითის არსი მდგომარეობს იმაში, რომ ავ­ტო­მობილის რთული სისტემა (ან ნებისმიერი სხვა რთული სისტემა) შეიძლება აღვწეროთ იერარქიული აბსტრაქ­ციის გზით.

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

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

აქ შეიძლება დაისვას სხვადასხვა კითხვა: მსოფლიოში არსე­ბობს ათასობით სხვადასხვა მარკისა და ტიპის ავტომო­ბი­ლები, რა არის მათ შორის საერთო? ხომ არ ჯობია ყველა განსხვავებული ტიპის ავტომობილისათვის ავაგოთ განსხვა­ვებული კლასი? როგორ მოვახდინოთ ყველა ამ კლასის ორგანიზება? ამ კითხვებზე ობიექტზე ორიენტირებული დაპროგრამება პასუხობს ასე: უნდა მოვახდინოთ კლასების იერარქიის ორგანიზება.

ობიექტზე ორიენტირებული დაპროგრამების სამი პრინციპი

ობიექტზე ორიენტირებული დაპროგრამების ყველა ენას აქვს მექანიზმები, რომლებიც აადვილებენ ობიექტზე ორიენ­ტირებული მოდელების აგებას. ამ მექანიზმებს წარმოადგენს ინკაფსულაცია, მემკვიდრეობითობა და პოლიმორფიზმი. განვიხილოთ ეს კონცეფციები.

ინკაფსულაცი

ინკაფსულაცია - ესაა მექანიზმი, რომელიც კოდს აკავშირებს იმ მონაცემებთან, რომლებთანაც ის მუშაობს და ორივე ამ კომპონენტს იცავს გარე ჩარევებისაგან და უნებართვო მი­მარ­თვებისაგან. ინკაფსულაცია შეიძლება წარმოვიდგინოთ, როგორც დამცავი გარსი, რომელიც კოდსა და მონაცემებს იცავს სხვა, ამ გარსის გარეთ მყოფი კოდის მიერ თავი­სუფალი წვდომისაგან (მიმართვისაგან). გარსის შიდა კოდსა და მონაცემებზე წვდომა (მიმართვა) მკაცრად კონტროლ­დება წინასწარ განსაზღვრული ინტერფეისით. რეალურ სამყაროსთან ანალოგიის მიზნით, განვიხილოთ ავტომობი­ლის სიჩქარის გადაცემათა კოლოფი. მასში ინკაფსული­რე­ბულია სხვადასხვა ინფორმაცია ავტომობილის შესახებ, მაგა­ლითად, აჩქარება, სავალი გზის ზედაპირის დახრილობა, სიჩქარის კოლოფის რეჟიმის გადამრთველის მდგომარეობა. მომხმარებელს (მძღოლს) ამ რთულ ინკაფსუალციაზე ზე­მოქ­მედება შეუძლია მხოლოდ ერთი გზით: სიჩქარეთა გადამრთველის სხვადასხვა პოზიციაში გადატანით. სიჩქა­რეთა კოლოფზე შეუძლებელია ვიმოქმედოთ მაგალითად, მოხვევის ნათურის გადამრთველით ან შუშების გამწმენდის ბერკეტით. ამრიგად, სიჩქარის გადაცემათა კოლოფზე მოქმე­დი ერთადერთი ინტერფეისია სიჩქარეთა გადამრთველი. გადა­ცემათა კოლოფის შიგნით მიმავალი პროცესები ზეგავ­ლენას არ ახდენენ მის გარეთ მყოფ ობიექტებზე (მაგალი­თად, არ ანათებს ფარებს!?). ვინაიდან სიჩქარეთა გადართვის ფუნქცია ინკაფსულირებულია გადაცემათა კოლოფში, ავტო­მო­ბილების ათობით სხვადასხვა გამომშვებმა ფირმამ კოლო­ფის რეალიზაცია შეიძლება მოახდინოს თავისი მეთოდით. მძღოლის კუთხით ყველა გადაცემათა კოლოფი ერთნაირად მუშაობს.

ანალოგიური მსჯელობა შეიძლება გამოვიყენოთ პროგრამი­რებაშიც. ინკაფსულირებული კოდის სიმძლავრე იმაში მდგო­­მარეობს, რომ ყველამ იცის როგორ მიმართოს მას და როგორ გამოიყენოს იგი რეალიზაციის ნიუანსების ცოდნის გარეშე.

Java-ში ინკაფსულაციის განხორციელების საფუძველს წარ­მო­ადგენს კლასი. თითოეული მოდელის აღწერა ხდება ერთი ან რამდენიმე კლასის (classes) საშუალებით. კლასი შეიძლება ჩავთვალოთ პროექტად, მონახაზად, შაბლონად, რომლის მიხედვითაც შემდგომში შეიქმნება კონკრეტული ობიექ­ტები. კლასი შეიცავს ობიექტის დამახასიათებელ ცვლადე­ბისა და კონსტანტების აღწერას. მათ უწოდებენ კლასის ველებს ან თვისებებს (class fields). ობიექტის მოქმედებების აღმწერ პროცედურებს უწოდებენ კლასის მეთოდებს (class methods). კლასის მეთოდები ან მოკლედ მეთოდები - ესაა პროგრამის კოდი, რომელიც ახდენს მონაცემების დამუშა­ვებას. ე.ი. კლასის წევრები შეიძლება იყოს ველები (თვისე­ბები, ცვლადები) და მეთოდები (პროცედურები).

სწორად დაწერილ Java პროგრამებში მეთოდები განსაზ­ღვ­რავს კლასის წევრი-ცვლადების გამოყენების ხერხს. ანუ კლასის ინტერფეისი და ურთიერთობა განისაზღვრება მე­თო­დებით, რომლებიც ახდენენ მოქმედებებს კლასის ეგზემ­პლარების მონაცემებზე.

კლასის შიგნით შეიძლება აღიწეროს ჩადგმული კლასები (nested classes) და ჩადგმული ინტერფეისები. ველები, მეთოდები, ჩადგმული კლასები წარმოადგენენ კლასის წევრებს (class members). სხვადასხვა სკოლები (ალგორით­მული ენები) სხვადასხვა ტერმინებს იყენებენ. ჩვენ გამოვი­ყენებთ ალგორითმულ ენა Java-ში მიღებულ ტერმინებს.

მაგალითად განვიხილოთ ავტომობილის აღწერის მონახაზი:


class Automobile {
[indent=1] int maxVelocity; // ველი, ავტომობილის მაქსიმალური სიჩქარე[/indent]
int speed; // ველი, ავტომობილის მიმდინარე სიჩქარე
int weight; // ველი, ავტომობილის მასა
// ..... სხვა ველები
void moveTo(int x, int y) { // მეთოდი, ავტომობილის
// გადაადგილების მოდელირება
// x და y პარამეტრები არაა ველები
int a = 1; // ლოკალური ცვლადი, არაა ველი
// ..... მეთოდის ტანი. აქ უნდა იყოს
// ავტომობილის (x,y) წერტილში
// გადაადგილების კანონის აღწერა
}
// სხვა მეთოდები
}

Pascal-ის მცოდნეებისათვის. Java-ში არ არსებობს ჩადგმული (შიდა) პროცედურები და ფუნქციები, მეთოდის ტანში არ შეიძლება სხვა მეთოდის აღწერა.

კლასის აღწერის შემდეგ შესაძლებელია ამ კლასის კონკრე­ტული ობიექტების, ეგზემპლარების (instances) შექმნა.

როგორც ზემოთ აღვნიშნეთ, კლასის დანიშნულებაა პროგრა­მის რთული სტრუქტურის ინკაფსულაცია, ამიტომ არსებობს მექანიზმი კლასის შიდა სტრუქტურის რეალიზაციის დასა­ფარად. კლასის შიგნით თითოეული მეთოდი ან ცვლადი შეიძლება მონიშნული იყოს როგორც პრივატული ან ყველა­სათვის წვდომადი (ღია). კლასის წევრებთან ღია, ყველასათ­ვის წვდომადი ინტერფეისი კლასის გარე მომხმა­რებლებს უფლებას აძლევს მიმართონ ამ წევრებს. კლასის პრივატული მეთოდები და ცვლადები წვდომადია მხოლოდ ამავე კლასის კოდისათვის. შესაბამისად, ნებისმიერო კოდი, რომელიც არაა იმავე კლასის წევრი ვერ მიიღებს უფლებას დაუკავ­შირდეს კლასის პრივატულ მეთოდს ან ცვლადს. ვინაიდან კლასის პრივატულ წევრებთან მიმართვა შესაძლებელია მხოლოდ კლასის ღია მეთოდების საშუა­ლებით, ამიტომ დარ­წმუნებული შეიძლება ვიყოთ, რომ შეუძლებელია პრი­ვა­ტულ წევრებზე უნებართვო მიმარ­თვები. ცხადია, ღია ინტერფეისი გააზრებულად უნდა იყოს დაპროექტებული, ვინაიდან ზომაზე მეტად არ გახსნას კლასის მუშაობის შიდა ნიუანსები (სურ. 1.).

68d181ab7b93.jpg

სურ.1. ინკაფსულაცია: ყველასათვის წვდომადი მეთოდები შეიძლება გამოყენებული იქნას პრივატული მონაცემების დასაცავად

Share this post


Link to post
Share on other sites

მემკვიდრეობითობა

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

როგორც წესი, ადამიანთა უმრავლესობა გარე სამყაროს აღიქვამს იერარქიულად ურთიერთ დაკავშირებული ობიექ­ტების სახით, მაგალითად, ცხოველები, ძუძუმწოვრები და ძაღლები. თუ საჭიროა ცხოველის ზოგადი, აბსტრაქტული აღწერა, მაშინ შეიძლება შემოვიღოთ შემდეგი ატრიბუტები: ზომები, ინტელექტის დონე, ჩონჩხის ტიპი. ცხოველებს ასე­ვე ახასიათებთ გარკვეული მსგავსი (ერთნაირი) ქმედე­ბებიც: ჭამა, სუნთქვა, ძილი. ჩამოთვლილი ატრიბუტები და ქცევე­ბი ფაქტიურად წარმოადგენს ცხოველთა კლასის აღწერას.

თუ საჭიროა ცხოველთა უფრო კონკრეტული კლასის აღწე­რა, მაგალითად ძუძუმწოვრების, საჭიროა უფრო კონკრეტუ­ლი ატრიბუტების მითითება, მაგალითად, კბილების ტიპი, სარძევე ჯირკვლები და სხვა. ამ აღწერას ვუწოდოთ ცხოვე­ლების კლასის ქვეკლასი. თავის მხრივ ძუძუმწოვ­რების კლასისათვის ცხოველების კლასი არის სუპერკლასი (მშობელი კლასი).

ვინაიდან ძუძუმწოვრები ესაა უფრო დაზუსტებულად გან­მარტებული ცხოველები, მათ აქვთ მემკვიდროებით გადმო­ცემული ცხოველების ყველა ატრიბუტი. კლასების იერარ­ქიის ქვედა დონის ქვეკლასი მემკვიდრეობით იღებს ყოველი თავისი მშობელი კლასის ატრიბუტებს (სურ.2 ).

da17ca836fa1.jpg

სურ. 2. კლასების იერარქიის სქემა

მემკვიდრეიბითობა ინკაფსულაციასთანაცაა კავშირში. თუ მოცემულ კლასს ინკაფსულირებული აქვს გარკვეული ატ­რი­ბუტები, მის ყოველ ქვეკლასსაც ექნება ეს ატრიბუტები და პლუს დამატებითი ატრიბუტები, რომლებიც წარმოად­გენენ მისი სპეციალიზაციის შემადგენელ ნაწილს (სურ.3).

bc118141ba57.jpg

სურ.3. კურცხალს მემკვიდროებით სრულად გადმოეცა ყველა მშობელი კლასის ინკაფსულირებული თვისებები

პოლიმორფიზმი

პოლიმორფიზმი (ბერძნულიდან ნიშნავს „მრავალ ფორმას“) - ესაა თვისება, რომელიც საშუალებას იძლევა ერთიდაიგივე ინტერფეისი გამოყენებული იქნას მოქმედებათა საერთო კლასზე. კონკრეტული მოქმედება განისაზღვრება კონკრე­ტული სიტუაციის ხასიათის მიხედვით. განვიხილოთ მონა­ცემთა სტეკური ორგანიზება (ესაა სიის ტიპი როდესაც „ბოლო მოსული პირველი გადის“ LIFO). მონაცემების ასეთი ორგანიზებისათვის შეიძლება დაგვჭირდეს სამი ტიპის სტეკი. ერთი სტეკი გამოიყენებოდეს მთელი რიცხვებისათ­ვის, მეორე - ნამდვილი ტიპის რიცხვებისათვის, მესამე - სიმბოლოებისათვის. თითოეული ამ სტეკის რეალიზაციის ალგორითმი ერთნაირია, იმისდა მიუხედავად, რომ თითო­ეული სხვადასხვა ტიპის მონაცემებს ინახავს. არა ობიექტ-ორიენტირებული ენისათვის საჭირო იქნებოდა სამი სხვა­დასხვა ქვეპროგრამის დაწერა, თითოეულ მათგანს უნდა ჰქონოდა განსხვავებული სახელი. Java-ში, პოლიმორფიზმის წყალობით შესაძლებელია სტეკის ქვეპროგრამები ისე შევქმნათ, რომ ყველას ერთიდაიგივე სახელი ჰქონდეს.

უფრო ზოგადად პოლიმორფიზმის კონცეფციას ასეთი ფრაზით აღწერენ: „ერთი ინტერფეისი, რამდენიმე მეთოდი“. ეს ნიშნავს, რომ შესაძლებელია დავაპროექტოთ საერთო ინტერფეისი ურთიერთდაკავშირებული მოქმედებების ჯგუ­ფისათვის. ასეთი მიდგომით შესაძლებელია პროგრამის სირთულის შემცირება, ვინაიდან ერთიდაიგივე ინტერფეისი გამოიყენება საერთო მოქმედებების კლასის აღნიშვნისათვის. კონკრეტული მოქმედების (ანუ მეთოდის) არჩევა კი ხდება, თითოეული სიტუაციის მიხედვით და ამას აკეთებს კომპი­ლატორი. პროგრამისტისათვის არაა აუცილებელი ამ არჩე­ვანის გაკეთება ხელით. საკმარისია მხოლოდ იცოდეს საერ­თო ინტერფეისი და და გამოიყენოს იგი.

თუ ძაღლებზე ანალოგიას განვაგრძობთ, შეიძლება ვთქვათ, რომ ძაღლის ყნოსვა პოლიმორფული თვისებაა. თუ ძაღლი კატის სუნს იყნოსავს იგი ყეფას დაიწყებს და გამოეკიდება მას. თუ ძაღლი საჭმლის სუნს იყნოსავს, მას დაეწყება ნერწყვის გამოყოფა და საჭმელის ჯამთან მივარდება. ორივე სიტუაციაში მოქმედებს ერთიდაიგივე შეგრძნება - ყნოსვა. განსხვავება ისაა, რა გამოსცემს ამ სუნს - ანუ მონაცემთა ტიპია განსხვავებული. ასეთი ზოგადი კონცეფცია შესაძ­ლებელია გამოყენებული იქნას Java-ში პროგრამის შიდა მეთოდების მიმართაც.

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

ამრიგად, ობიექტზე ორიენტირებული პროგრამირება წარმოადგენს პროგრამირების მეთოდოლოგიას, რომელიც ემყარება პროგრამის წარმოდგენას ობიექტების ერთობ­ლიობის სახით, სადაც თითოეული ობიექტი არის გან­საზ­ღვრული ტიპის რეალიზაცია, რომელიც იყენებს შეტყობი­ნებების (გზავნილების) გადაგზავნის მექანიზმს და მემკვიდ­რეობის იერარქიულად ორგანიზებულ კლასებს.

ობიექტზე ორიენტირებული პროგრამირების ძირითადი ელემენტია აბსტრაქცია. მონაცემები აბსტრაქციის საშუ­ალე­ბით გარდაიქმნება ობიექტებად, მონაცემების დამუშავების მიმდევრობა კი ხდება ამ ობიექტებს შორის გადაცემული შეტ­ყობინებების ერთობლიობა. თითოეული ობიექტი უნი­კა­ლურია. ობიექტებთან ურთიერთობა ხდება, როგორც კონ­კრე­ტულ არსებებთან, რომლებიც რეაგირებენ რაიმე ბრძა­ნე­ბე–ბის შესრულების შეტყობინებებზე.

ობიექტზე ორიენტირებული პროგრამირება ხასიათდება შემ­დეგი პრინციპებით (ალან კეის მიხედვით):

· ყველაფერი ობიექტის სახითაა წარმოდგენილი;

· გამოთვლები ხორციელდება ობიექტებს შორის ურთი­ერთ­ქმედებით (მონაცემების გაცვლით), ამ დროს ერთი ობიექტი ითხოვს, რომ მეორე ობიექტმა შეასრულოს გარკვეული მოქმედებები; ობიექტები ურთიერთქმედებენ ერთმანეთში შეტყობინებების გადაცემით და მიღებით; შეტყობინებები ესაა მოთხოვნა რაიმე მოქმედების შესას­რუ­­ლებლად, რომელსაც დამატებით შეიძლება ჰქონდეს არგუმენტები ამ მოქმედებების სამართავად;

· თითოეულ ობიექტს აქვს დამოუკიდებელი მეხსიერება, რომელიც სხვა ობიექტებისაგან შედგება;

· ყოველი ობიექტი არის ამ ტიპის ობიექტების საერთო თვისებების გამომხატავი კლასის წარმომადგენელი;

· კლასში მოცემულია ობიექტის ქცევა (ფუქციონალობა), ამიტომ კლასის ყველა ეგზემლიარს (ობიექტს) შეუძლია ერთიდაიგივე მოქმედებების შესრულება;

· კლასები ორგანიზებულია საერთო ძირიანი ხისებური იერარქიის სახით, რომელსაც მემკვიდრეობის იერარქია ქვია; კლასის ეგზემპლიარის მეხსიერება და ქცევა ავტომატურად წვდომადია ყველა იმ კლასისათვის, რომელიც იერარქიულ ხეზე მასზედ დაბლაა განლაგებული.

Share this post


Link to post
Share on other sites

ენის ლექსიკა, ბაზისური ტიპები და ოპერაციები მათზე

ახალი ენის შესასწავლად განვიხილოთ, რა ტიპის საწყისი მონაცემების დამუშავება შეიძლება ამ ენის საშუალებთ, რა სახით შეიძლება მათი აღწერა და რა სტანდარტული საშუ­ალებებია ჩადებული ენაში. ალგორითმულ ენა Java-ში მრა­ვა­ლი მონაცემთა ტიპი და კიდევ უფრო მეტი მათი გამო­ყენების წესი არსებობს. ამ წესების დაუცველობა იწვევს და­ფა­რულ შეცდომებს, რომლების აღმოჩენაც საკმაოდ ძნელი და შრომატევადი სამუშაოა.

ტრადიციის მიხედვით, მრავალი სახელმძღვანელო იწყება უმარტივესი პროგრამით “Hello World!”. ლისტინგ 1-ზე ნაჩ­ვე­ნებია Java-ზე დაწერილი ეს პროგრამა

ლისტინგი 1. Java-ზე დაწერილი პირველი პროგრამა

class HelloWorld {	 public static void main(String[] args) {			 System.out.println("Hello World!");	 }}

ამ მარტივ მაგალითზეც შესაძლებელია შევამჩნიოთ ენის მთელი რიგი თავისებურებები:

- ყოველი პროგრამა წარმოადგენს ერთ ან რამოდენიმე
კლასს,
ჩვენ მაგალითში მხოლოდ ერთი კლასია (class).

- კლასის დასაწყისს აღნიშნავს დარეზერვირებული სიტ­ყვა class, რომლის შემდეგაც მოდის პროგრამისტის მიერ შერჩეული კლასის კონკრეტული სახელი, ჩვენ შემთხვე­ვაში HelloWorld. ყველაფერი რაც კლასს ეკუთ­ვნის ჩაიწე­რე­ბა ფიგურულ ფრჩხილებში და წარმოად­გენს კლასის ტანს (class body).

- ყოველი მოქმედება (გამოთვლები) ხდება ინფორმაციის დამუშავების მეთოდების საშუალებით, მოკლედ ამბო­ბენ მეთოდებით (method). Java-ში მიღებულია ეს ტერმი­ნი „ფუნქციის“ მაგივრად, რომელიც სხვა ენებში გამო­იყე­ნება.

- მეთოდებს აქვთ განსხვავებული სახელები. ერთ-ერთი მეთოდის სახელი აუცილებლად უნდა იყოს main, ამ მეთოდით იწყება პროგრამის შესრულება. ჩვენ მარტივ მაგალითში ერთი მეთოდია, ამიტომ მისი სახელია main.

- როგორც წესი ფუნქცია, ჩვენ შემთხვევაში მეთოდი, შედე­გად იძლევა (ხშირად ვამბობთ აბრუნებს - returns) ერთ მნიშ­ვნელობას, რომლის ტიპი მეთოდის სახელის წინ მიეთითება. მეთოდმა შეიძლება არაფერიც არ დააბ­რუ­ნოს, როდესაც იგი პროცედურის როლს ასრუ­ლებს, როგორც ეს ჩვენ შემთხვევაშია. ასეთ შემთხვევაში დაბ­რუნებული მნიშვნელობის ტიპის მაგივრად ჩაიწერება სიტყვა void.

- მეთოდის სახელის შემდეგ ფრჩხილებში ჩაიწერება არგუმენტების ან პარამეტრების ჩამონათვალი, რომლე­ბიც ერთმანეთისაგან მძიმეებით გამოიყოფა. ყოველი არგუ­მენ­ტისათვის მიეთითება მისი ტიპი და ცარიელი სიმ­ბო­ლოს შემდეგ სახელი. მაგალითში მხოლოდ ერთი არგუ­მენ­ტია, ის სტრიქონული მასივის ტიპისაა. სიმბო­ლოების მასივი - ესაა Java-ში არსებული String ტიპი. კვადრა­ტუ­ლი ფრჩხილები მიუთითებს მასივს. მასივის სახელად ნების­მიერი სახელი შეიძლება იყოს, მაგალით­ში არჩე­უ­ლია args.

- მეთოდის დაბრუნებული ტიპის წინ შეიძლება ჩაწე­რილი იქნას სხვადასხვა
მოდიფიკატორები
(modifiers). მაგა­ლით­ში ორი მოდიფიკატორია: სიტყვა public აღნიშ­ნავს, რომ ეს მეთოდი წვდომადია ყველასათვის; სიტყვა static უზრუნ­ველყოფს main() მეთოდის გამოძახების შესაძლებლობას პროგრამის შესრულების დასაწყისში. ზოგადად მოდიფი­კა­ტორები არაა აუცილებელი, მაგრამ main() მეთო­დი­სა­თვის ისინი აუცილებელია. ყოველ­თვის მეთოდის სახე­ლის შემდეგ ვწერთ ფრჩხილებს, ამით ხაზს ვუსვამთ, რომ ეს მეთოდის სახელია და არა ჩვეულებრივი ცვლადის სახე­ლი.

- მეთოდის მთელი შემცველობა წარმოადგენს მეთოდის
ტანს
(method body) და ჩაიწერება ფიგურულ ფრჩხი­ლებში.

ერთადერთი მოქმედება, რაც main() მეთოდში ხდება - ესაა სხვა მეთოდის გამოძახება, რომელსაც რთული სახელი აქვს System.out.println() და მას გადაეცემა ერთი არგუმენტი, ტექსტური კონსტანტა „Hello World!“. ტექსტური კონსტანტა ჩაიწერება ორმაგ ბრჭყალებში, რომლებიც გამყოფს წარმო­ადგენენ და ტექსტის შემადგენლობაში არ შედიან. println() მეთოდი თავის არგუმენტს გაიტანს გამავალ ნაკადში, რომელიც, ჩვეულებრივ, ტექსტური ტერმინალის ეკრანთანაა დაკავშირებული. ტექსტის გამოტანის შემდეგ, კურსორი გადადის შემდეგი სტრიქონის დასაწყისში (ამას მიუთითებს დაბოლოება ln, სიტყვა println – შემოკლებით print line). მნიშვნელოვანია აღინიშნოს, რომ Java-ს კომპი­ლატორი განასხვავებს დიდ და პატარა ასოებს. პროგრამაში სიტყვები String, System უნდა დაიწყოს დიდი ასოებით, ხოლო main პატარა ასოთი. ტექსტური კონსტანტის შიგნით კი არაა მნიშვნელოვანი პატარა ასოები იქნება თუ დიდი, განსხვავება მხოლოდ ეკრანზე გამოჩნდება.

ალგორითმულ ენა Java-ში პროგრამისტის მიერ შერჩეული სახელები შეიძლება ჩაიწეროს მისი შეხედულებისამებრ, კლასისთვის შეიძლება დაგვერქმია helloworld ან helloWorld, მაგრამ java-პროგრამისტებს შორის მოქმედებს შეთანხმება, რომელსაც უწოდებენ „Code Conventions for the Java Programming Manguage“, რომელსაც შეიძლება გაეცნოთ java.sun.com/docs/codeconv/index.html მისამართზე. ამ შეთანხმების ზოგიერთი პუნქტი ასეთია:

- კლასის სახელები იწყება დიდი ასოებით; თუ სახელი შედ­გება რამდენიმე სიტყვისაგან, ყოველი შემდეგი სიტ­ყვა უნდა იწყებოდეს დიდი ასოთი;

- ცვლადებისა და მეთოდების სახელები უნდა იწყებოდეს პა­ტარა ასოთი; თუ სახელი შედგება რამდენიმე სიტ­ყვი­სა­გან, ყოველი შემდეგი სიტყვა უნდა იწყებოდეს დიდი ასოთი;

- კონსტანტების სახელები იწერება მხოლოდ დიდი ასოე­ბით; თუ სახელი შედგება რამდენიმე სიტყვისაგან, ყო­ველ სიტ­ყვას შორის უნდა ჩაიწეროს ხაზის გასმის სიმბოლო;

ეს წესები არაა აუცილებელი, მაგრამ მათი დაცვა მნიშვ­ნე­ლოვ­ნად აადვილებს პროგრამის კოდის კითხვადო­ბას და მას აძ­ლევს Java-ს სტილს.

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

კომპილატორისათვის პროგრამირების სტილს მნიშვნელობა არა აქვს, იგი მთელ პროგრამას განიხილავს, როგორც ერთ, მთლიან სტრიქონს, მაგრამ სასურველია დავიცვათ აღნიშ­ნული შეთანხმება.

რომელიმე რედაქტორში შექმნილი პროგრამის შენახვა უნდა მოხ­დეს ფაილში, რომლის გაფართოება იქნება .java, თუ ამ პი­რობას დავიცავთ, ოპერაციულ სისტემას გაუადვილდება ამ ფაილთან ასოცირებული პროგრამის გამოძახება. სასურ­ვე­ლია ფაილს დაერქვას კლასის სახელი, ასოების რეგისტრის შენარ­ჩუნებით, თუ ფაილში რამდენიმე კლასია, დაარქვით main() მეთოდის შემცველი კლასის სახელი.

ლექსიკის საკითხები

პატარა Java-პროგრამის გაცნობის შემდეგ შესაძლებელია უფრო ფორმალურად აღვწეროთ ენის ძირითადი ელემენ­ტები. Java პროგრამა წარმოადგენს ცარიელი სიმბო­ლოების, იდენტიფიკატორების, კონსტანტების, კომენ­ტა­რე­ბის, ოპერ­აციების, გამყოფებისა და საკვანძო სიტყვების კოლექციას.

ცარიელი სიმბოლო

Java თავისუფალი ფორმატის ენაა. ეს ნიშნავს, რომ პროგრა­მის დაწერისას არაა საჭირო რაიმე სპეციალური წესების დაცვა აბზაცების მიმართ. ერთადერთი აუცილე­ბელი მოთ­ხოვ­ნაა, რომ ყოველ ლექსემას შორის, რომლებიც არაა ოპერა­ციის სიმბოლოთი ან გამყოფით გამოყოფილი, ჩასმული იყოს ერთი ცარიელი სიმბოლო მაინც. Java-ში ცარიელ სიმ­ბო­ლოდ ითვლება ჰარი (space), ტაბულაცია ან ახალი სტრიქონის სიმბოლო.

იდენტიფიკატორები

იდენტიფიკატორი გამოიყენება კლასების, მეთოდების და ცვლადების დასახელებისათვის. იდენტიფიკატორი შეიძლე­ბა იყოს დიდი და პატაა ასოების, ციფრების, ხაზგასმისა და დოლარის სიმბოლოს ნებისმიერი მიმდევრობა. იდენტიფი­კატორი არ უნდა იწყებოდეს ციფრით, ვინაიდან კომპი­ლატორს არ აერიოს რიცხვით კონსტანტებში. ისევ გავი­მეოროთ, რომ ჯავა დიდ და პატარა ასოების მიმართ მგრძნობიარეა. მაგალითად VALUE და Value სხვადასხვა იდენტიფიკატორებია. კორექტული იდენტიფიკატორების მაგალითებია:

AvgTemp

count

a4

$test

this_is_ok

შემდეგი დასახელებები დაუშვებელია:

2count

high-temp

Not/ok

კომენტარები

პროგრამის ტექსტში შეიძლება ჩავსვათ კომენტარები, რომელ­საც კომპილატორი არ გაითვალისწინებს. ისინი ძალიან მნიშვნელოვანია პროგრამის მიმდინარეობის განმარ­ტებისათვის. პროგრამის გამართვისას შესაძლებელია ერთი ან რამდენიმე ოპერატორი გამოვრთოთ განხილვისგან, მათი კომენტარებათ მონიშვნის გზით ანუ „დავაკომენტიროთ“.

Java-ში შესაძლებელია სამი ტიპის კომენტარის გამოყენება:

- კომენტარი იწყება ორი დახრილი ხაზის შემდეგ // (ხაზებს შო­რის არ უნდა იყოს ცარიელი სიმბოლო) და გრძელდება სტრი­ქონის ბოლომდე;

- კომენტარი იწყება დახრილი ხაზისა და ვარსკვლავის სიმბო­ლოთი /*, რომელიც შეიძლება გრძელდებოდეს რამ­დე­ნიმე სტრიქონზე და მთავრდება ვარსკვლავით და დახ­რი­ლი ხაზით */ (ამ სიმბოლოებს შორის ცარიელი სიმ­ბო­ლო არ უნდა იყოს).

- კომენტარი იწყება დახრილი ხაზისა და ორი ცალი ვას­კვლა­ვისაგან /** და მთავრდება */ -ით. შეიძლება დაიკავოს რამ­დენიმე სტრიქონი, იგი მუშავდება სპეცი­ალური პროგ­რამა javadoc-ის მიერ. კომენტარების ეს ტიპი გამოიყენება თვითდოკუმენტირებისთვის.

გამყოფები

Java-ში რამდენიმე სიმბოლო შესაძლებელია გამყოფად იქნას გამო­ყენებული. ცხრილი 1-ში ჩამოთვლილია გამყოფი სიმ­ბოლოები.

ცხრილი 1. დასაშვები გამყოფი სიმბოლოები

სიმბოლო

დასახელება

დანიშნულება

()

მრგავლი ფრჩილები

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

{}

ფიგურული ფრჩხილები

გამოიყენება მასივების ინიციალიზაციისას მნიშვნელობების განსასაზღვრავად. მათ იყენებენ ასევე კოდების, კლასების, მეთოდების და ლოკალური განსაზღვრე­ბების ბლოკების მისათითებლად.

[]

კვადრატუი ფრჩხილები

გამოიყენება მასივების ტიპების გამოსა­ც­ხა­დებ­ლად, ასევე მასივების ელემენტების შემო­სატანად.

;

წერტილმძიმე

აღნიშნავს ოპერატორის დასრულებას

,

მძიმე

გამოიყენება ცვლადების გამოცხადების დროს ჩამონათვალში იდენტიფიკატორების სახე­ლების გამოსაყოფად. ეს სიმბოლო გამყო­ფი ასევე შესაძლებელია გამოყენებულ იქნას ოპერატორები ჯაჭვის შესაქმნელად FOR ოპერატორში

.

წერტილი

განოიყენება პაკეტის სახელის გამოსყოფად ქვეპაკეტებისა და კლასებისაგან, აგრეთვე ცვლადებისა და მეთოდების გამოსაყოფად მიმთითებელი ცვლადისაგან

საკვანძო სიტყვები

დღეისათვის Java-ში განსაზღვრულია 50 საკვანძო სიტყვა (ცხრილი 2. ) ეს სიტყვები არ შეიძლება გამოყენებული იქნას ცვლადების, კლასებისა და მეთოდების სახელებად.

ცხრილი 2. საკვანძო სიტყვები

b91b80990756.jpg

const და goto საკვანძო სიტყვები ასევე დარეზერვირებულია, მაგრამ არ გამოიყენება.

საკვანძო სიტყვების გარდა Java-ში ასევე დარეზერვირე­ბულია სიტყვები true, false და null. ისინი წარმოადგენენ მნიშვნელობებს და ისინიც არ გამოიყენება სახელებად.

ელემენტარული (ბაზისური, პრიმიტიული) ტიპები Java-ში

როგორც ყველა სხვა თანამედროვე ალგორითმული ენაში, Java-შიც არსებობს მონაცემთა სხვადასხვა ტიპები. ეს ტიპები გამოიყენება ცვლადების აღწერისათვის, მასივების გამოცხა­დებისათვის და ა.შ.

განსაკუთრებით უნდა აღვნიშნოთ, რომ Java არის მკაცრად ტიპიზებული ენა. ამ გარემოებით მიიღწევა Java პროგრამე­ბის განსაკუთრებული საიმედობა და უსაფრთხოება. მკაცრი ტიპიზაცია განპირობებულია იმით, რომ:

· თითოეულ ცვლადს და თითოეულ გამოსახულებას აქვს გარკვეული ტიპი, რომელიც მკაცრადაა განსაზღვრული;

· ყოველი მინიჭებისას, როგორც ცხადი, ისე მეთოდების გამოძახების დროს პარამეტრების გადაცემისას, მოწმ­დება, შეესაბამება თუ არა ტიპები ერთმანეთს.

Java-ში არ არსებობს რაიმე ავტომატური საშუალებები კონ­ფლიქტური ტიპების დაყვანის ან გარდაქმნის, როგორც ეს ბევრ სხვა ენაშია განხორციელებული. Java-ს კომპი­ლა­ტორი ამოწმებს ყველა გამოსახულებასა და პარამეტრს ტიპების შესაბამისობაზე. ნებისმიერი შეუსაბამობა ითვლება შეცდო­მად, რომელიც უნდა გასწორდეს კლასის კომპილა­ციის დასრულებამდე.

ხშირად სხვადასხვა ლიტერატურაში ელემენტარულ ტიპებს უწოდებენ მარტივს, ბაზისურს ან პრიმიტიულს. პრაქტიკუ­ლად ეს ტერმინები ამ შემთხვევაში სინონიმებია.

საწყისი მონაცემების ყველა ტიპი, რომლის აღწერაც შესაძლებელია Java-ში, იყოფა ორ ჯგუფად: პრიმიტიული (primitive types) და აღწერითი (reference types მიმთითებელი, მისამართი, მაკავშირებელი) ტიპები.

აღწერითი ტიპები იყოფა მასივებად (arrays), კლასებად (classes) და ინტერფეისებად (interfaces). ამ ტიპებს ჩვენ მომავალში განვიხილავთ დაწვრილებით.

პრიმიტიული სულ 8 ტიპია. ისინი შეიძლება დაიყოს რიცხვით (numeric), სიმბოლურ (character) და ლოგიკურ (boolean ბულის) ტიპებად.

რიცხვითი ტიპები თავის მხრივ იყოფა მთელრიცხვა (integer) და ნამდვილ (floating-point) ტიპებად:

-
მთელრიცხვა.
ამ ჯგუფში შედის byte, short, int, long ტიპები, რომლებიც წარმოადგენენ ნიშნიან მთელ რიცხვებს;

-
ნამდვილი (მცოცავმძიმიანი) რიცხვები.
ამ ჯგუფში შედის float, double ტიპები, ისინი წარმოადგენენ ნიშნიან წილად რიცხვებს, რომლებიც ათობითი წერტილის შემდეგ თანრი­გების გარკვეული სიზუსტით მოიცემა;

სიმბოლოების ტიპია char, რომელიც წარმოადგენს ენაში დაშვებულ ყველა სიმბოლოს, მაგალითად, ასოები, ციფრები, სასვენი ნიშნები, სპეციალური სიმბოლოები და სხვა. ხშირად ამ ტიპს მიაკუთვნებენ მთელრიცხვა ტიპს და განიხილავენ როგორც უნიშნო მთელ რიცხვს.

ლოგიკური ანუ ბულის ტიპია boolean. ესაა სპეციალური ტიპი, რომელიც ჭეშმარიტი (true) ან ყალბი (false) მნიშ­ვნელობის წარმოსადგენად გამოიყენება.

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

ელემეტარული ტიპები აღწერენ რაიმე ერთ მნიშვნელობას და არა რთულ სტრუქტურებს ან ობიექტებს. Java-ში ამ 8 ტიპის გარდა სხვა ტიპები აკმაყოფილებს ობიექტზე ორიენტირებული ენის მოთხოვნებს ანუ რთული ტიპისაა (შეიძლება იყოს მასივი, კლასი, ინტერფეისი). ეს განსაკუთ­რებულობა გამოწვეულია მაქსიმალური ეფექტუ­რობის მიღ­წე­ვის სურვილით.

ელემნტარული ტიპები ისეა განსაზღვრული, რომ მათთვის ცხადად და მკაცრადაა განსაზღვრული დასაშვები მნიშვნელობების არე (დიაპაზონი). Java-ს სხვადასხვა პლატფორმაზე გადატანადობის გამო, მას მოეთხოვება მონაცემთა ყველა ტიპი მკაცრად იყოს ერთნაირად წარმოდგენილი ყველა მანქანური არქიტექტურისათვის.

განვიხილოთ თითოეული მონაცემთა ტიპი.

მთელრიცხვა ტიპები (მნიშვნელობები)

როგორც ზემოთ აღვნიშნეთ Java-ში 4 მთელრიცხვა ტიპია: byte, short, int, long. ამ ენაში არაა განსაზღვრული მთელი უნიშნო რიცხვების ტიპი, როგორც ეს ბევრ სხვა ენაშია დაშვებული.

ცხრილ 1-ში ნაჩვენებია თითოეული ამ ტიპის მიერ დაკავე­ბული მეხსიერების ზომა, დასაშვები მნიშვნელობების დიაპაზონი და სტანდარტული მნიშვნელობა გამოცხადების შემდეგ.

ცხრილი 1. მთელი ტიპის რიცხვების თანრიგების რაოდენო­ბა და დიაპაზონი

2ff7a3e40670.jpg

byte

ზომის მიხედვით ყველაზე პატარაა ტიპი byte. ეს ტიპი ხშირად გამოიყენება მონაცემთა ნაკადებთან სამუშაოდ, რომ­­ლებიც ქსელიდან ან რომელიმე ფაილიდან მიიღე­ბა/გაიცემა. ასევე მოსახერხებელია მათი გამოყენება ისეთ ორობით მონაცემებზე სამუშაოდ, რომლებიც არაა თავსება­დი Java-ს არსებულ ტიპებთან.

ამ ტიპის ცვლადის გამოსაცხადებლად გამოიყენება საკვანძო სიტყვა byte. მაგალითად, შემდეგ სტრიქონში გამოცხა­დე­ბუ­ლია ორი byte-ს ტიპის ცვლადი a და b:

byte a, b;

short

short ტიპი ყველაზე იშვიათად გამოიყენება. ამ ტიპის ცვლადების გამოცხადების მაგალითია:

short s;

short h;

int

int ტიპი ყველაზე ხშირად გამოყენებული ტიპია. იგი ხშირად გამოიყენება ციკლებისა და მასივების ინდექსების აღსანიშნავად. აღსანიშნავია, რომ გამოსახულებების გამოთ­ვლი­სას, სადაც მონაწილეობს byte და short ტიპის მნიშვნე­ლო­ბების მქონე ცვლადები ან კონსტანტები, მათი ტიპი ამაღ­ლდე­ბა int-მდე და ისე მოხდება არითმეტიკული ოპერა­ცი­ები.

long

long ტიპის გამოყენება ხდება მაშინ, როდესაც int ტიპის დიაპაზონი არაა საკმარისი საჭირო მნიშვნელობის შესანა­ხად. გამოიყენება დიდ მთელ რიცხვებთან სამუშაოდ.

მცოცავმძიმიანი ტიპები

მცოცავმძიმიანი ტიპის რიცხვებს ასევე უწოდებენ ნამდვილი ტიპის რიცხვებს და ისინი გამოიყენება გამოსახულებების გამოთვლისას, როდესაც საჭიროა შედეგების მიღება ათო­ბი­თი წერტილის შემდეგ გარკვეული სიზუსტით. Java-ში რე­ალი­ზებულია IEEE-754 სტანდარტის შესაბამისი ტიპები და მცოცავმძიმიანი ოპერაციები. მათი ზომები, დიაპაზონები, გამოცხადების შემდეგ სტანდარტული მნიშვნელობები და სიზუსტე ნაჩვენებია შემდეგ ცხრილში:

ცხრილი 2. ნამდვილი ტიპის რიცხვების თანრიგების რაოდენო­ბა და დიაპაზონი

701e9ff82ac4.jpg

float

float ტიპი განსაზღვრავს ერთმაგი სიზუსტის მნიშ­ვნე­ლო­ბებს, რომლებიც შესანახად იკავებენ 32 ბიტს. ამ ტიპის ცვლა­დე­ბი გამოიყენება როდესაც წილადი ნაწილის დიდი სიზუს­ტე არაა საჭირო. ამ ტიპის ცვლადის გამოცხადების მაგალითია:

float boxHigh, boxWidth;

double

ორმაგი სიზუსტე, რასაც მიანიშნებს დასახელების საკვანძო სიტყვა double (ორმაგი), ითხოვს 64 ბიტის გამოყენებას მნიშვნელობების შესანახად. ბევრ თანამედროვე პროცესორ­ში ამ ტიპის რიცხვებზე მოქმედებები უფრო სწრაფად სრულ­დე­ბა, ვიდრე ერთმაგი სიზუსტისას. ყველა ტრანსცენ­დენ­ტუ­ლი მათემატიკური ფუნქციები, როგორიცაა sin(), cos(), sqrt() და სხვა, აბრუნებენ double ტიპის შედეგებს.

სიმბოლური ტიპი

Java-ში სიმბოლოების შესანახად გამოიყენება char ტიპი. უნდა აღვნიშნოთ, რომ ეს ტიპი ალგორითმულ ენა C-შიც გამოიყენება, მაგრამ ისინი ეკვივალენტური არ არის. C-ში char - ესაა 8 ბიტიანი მთელრიცხვა ტიპი. Java-ში ეს ასე არაა, აქ სიმბოლოს წარმოდგენისათვის გამოიყენება Unicode.

Unicode სტანდარტი განსაზღვრავს სიმბოლოების საერთა­შორისო ნაკრებს, რომელიც მოიცავს ყველა ცნობილი ენების სიმბოლოებს. იგი წარმოადგენს ათობით სხვადასხვა სიმ­ბო­ლო­ების უნიფიცირებულ ერთობლიობას, როგორიცაა ქარ­თუ­ლი, ბერძნული ალფაბეტი, არაბული ალფაბეტი, კირი­ლი­ცა, ივრითი, იაპონური იეროგლიფები და სხვა. ყველა ამ სიმბოლოს კოდის შესანახად საჭიროა 16 ბიტი. ამიტომ Java-ში char ტიპის შესანახად გამოიყენება 16 ბიტი. ამ ტიპის მნიშვნელობების დასაშვები დიაპაზონია 0 ÷ 65536. char ტიპისთვის არ არსებობს უარყოფითი მნიშვნელობები. სიმ­ბო­ლოების ნაკრების ცნობილ ASCII სტანდარტში მნიშ­ვნე­ლო­ბები იცვლება 0 ÷ 127 დიაპაზონში, ხოლო გაფარ­თო­ებულ 8 ბიტიან სტანდარტში ISO-Latin-1 მნიშვნელობები 0 ÷ 255 დიაპაზონშია. ვინაიდან Java განკუთვნილია პროგრა­მე­ბის შესაქმნელად მთელ მსოფლიოში, ამიტომ Unicode სტან­დარ­ტის გამოყენება ენაში გასაგებია. რა თქმა უნდა Unicode-ს გამო­ყე­ნება არაა ეფექტური ლათინურენოვანი დამწერლობის მქო­ნე ენებისათვის, რომლებისთვისაც სავსებით საკმარისია 8 ბიტიანი კოდირებები, მაგრამ სამაგიეროდ ეს აუცილე­ბე­ლია მსოფლიო მასშტაბით პროგრამების თავსებადობისა და გადატანა­დობისათვის.

აღსანიშნავია char ტიპის კიდევ ერთი თავისებურება. ვინა­იდან იგი გათვალისწინებულია Unicode სიმბოლოების შესანა­ხად, იგი შეიძლება ჩავთვალოთ მთელ ტიპადაც, რო­მელ­ზეც არითმეტიკული ოპერაციების ჩატარებაც შესაძ­ლე­ბე­ლია. მაგალითად, შესაძლებელია სიმბოლური ცვლადის მნიშ­ვნელობის გაზრდა ან შემცირება. განვიხილოთ პროგ­რა­მის ფრაგმენტი:

// სიმბოლური ცვლადები იქცევიან მთელრიცხვა ტიპებივით

class CharDemo2 {

public static void main(String args[]) {

char chl;

­ ch1 = 'Х';

System.out.println ("chl მნიშვნელობაა " + chl);

chl++; // chl მნიშვნელობის 1-ით გაზრდა

System.out.println("chl ახალი მნიშვნელობაა " + chl);

}

}

ამ პროგრამის შედეგად კონსოლზე გამოვა:

chl მნიშვნელობაა X

chl ახალი მნიშვნელობაა Y

პროგრამაში chl ცვლადს თავიდან ენიჭება მნიშვნელობა Х. შემდეგ chl ცვლადის მნიშვნელობა იზრდება 1-ით. შედეგად chl ცვლადში ინახება სიმბოლო Y, ვინაიდან მისი კოდი ASCII (და Unicode-შიც) Х-ს შემდეგია, ანუ Y-ის კოდი ერთით მეტია Х-ის კოდზე.

ლოგიკური (ბულის) ტიპი

Java-ში გამოყენებულია ელემენტარული ტიპი, რომელიც boolean-ით აღინიშნება და მისი მნიშვნელობა შეიძლება იყოს ლოგიკური true (ჭეშმარიტი) ან false (მცდარი). ასეთი ტიპი ბრუნდება ყველა შედარების ოპერაციის შედეგად (მაგალი­თად, a > B). აუცილებელია boolean ტიპის იყოს ასევე პირობითი და ციკლის ოპერატორებში გამოყენებული პირობითი გამოსახულების შედეგი.

კონსტანტები (ლიტერალები)

კონსტანტები შეიძლება დავყოთ რიცხვით, რომელიც თავის მხრივ იყოფა მთელრიცხვა და მცოცავმძიმიან (ნამდვილ) კონსტანტებად, სიმბოლურ, ლოგიკურ და სტრიქონულ კონ­სტანტებად. განვიხილოთ თითოეული მათგანი დეტალუ­რად.

მთელრიცხვა კონსტანტები

მთელი რიცხვები ტიპიურ პროგრამაში ყველაზე უფრო ხშირად გამოყენებადი ტიპია. ნებისმიერი რიცხვითი მნიშ­ვნე­ლობა რიცხვითი კონსტანტაა. მისი მაგალითებია 0, 1, -17, 1024 და სხვა. ყველა ეს კონსტანტა წარმოადგენს ათობით რიც­ხვებს. რიცხვით კონსტანტებში გამოყენებული შეიძლება იყოს კიდევ ორი სახის წარმოდგენა - რვაობითი (რიცხვები 8-ის ფუძით) და თექვსმეტობითი (რიცხვები თექვსმეტის ფუძით).

Java-ში რვაობითი მნიშვნელობა აღინიშნება საწყისი 0-ით. ჩვეულებრივ ათობით რიცხვები არ უნდა იწყებოდეს 0-ით. გარეგნულად ჩვეულებრივი და დასაშვები მნიშვნელობა 09 იწვევს კომპილაციის შეცდომას, ვინაიდან რახან რიცხვი იწყება 0-ით, კომპილატორი თვლის, რომ უნდა მოდიოდეს რვაობითი რიცხვი, ხოლო რვაობითში ციფრი 9 დაუშვე­ბელია! რვაობითში ციფრები დასაშვებია მხოლოდ 0-7 დი­აპა­ზონში. რვაობითში ჩაწერილი კორექტული კონ­სტან­ტებია: 017, -02003, 0777.

პროგრამისტები ხშირად იყენებენ რიცხვების თექვსმეტობით წარმოდგენას, რომლებიც ზუსტად შეესაბამება მანქანური სიტყვებს, რომელთა ზომებია 8, 16, 32 და 64 ბიტი. თექვს­მე­ტო­ბითი მნიშვნელობა აღინიშნება საწყისი 0-ით და სიმბოლო x-ით (0x ან 0X). თექვსმეტობითში სულ დასაშ­ვებია 16 ციფრი, ეს ციფრებია 0,1,...9,A,B,C,D,E,F (ან a, b, c, d, e, f). თექვსმეტობითში ჩაწერილი კორექტული კონსტან­ტებია: 0x17, 0xff0b, 0X77FF, -0X12cd.

მთელრიცხვა კონსტანტები ქმნიან int ტიპის მნიშვნელობას, რომელიც java-ში 32 ბიტიანია. როგორც ზემოთ აღვნიშნეთ ეს ენა მკაცრად ტიპიზებულია, მაშინ შეიძლება დაისვას კითხვა როგორ უნდა მიენიჭოს მთელრიცხვა კონსტანტა სხვა მთელ ტიპებს, მაგალითად, byte-ს, short-ს ან long-ს ისე, რომ არ მოხდეს ტიპების შეუსაბამობის შეცდომა. საბედნიეროდ ასეთ სიტუაციებს კომპილატორი ადვილად უმკლავდება. როდესაც კონსტანტის მნიშვნელობა ენიჭება byte-ს ან short-ს თუ მნიშვნელობა იმყოფება მიმღების დასაშვებ დიაპაზონში შეცდომა არ წარმოიქმნება. გარდა ამისა long ტიპის ცვლადს ყოველთვის შეიძლება მიენიჭოს მთელრიცხვა კონსტანტა. მაგრამ თუ საჭიროა კომპილატორს ცხადად მივუთითოთ, რომ კონსტანტა long ტიპისაა, კონსტანტას უკან უნდა მივუწეროთ l ან L ასო. გასათვა­ლისწინებელია, რომ გრძელი მთელი კონსტანტების ჩაწე­რისას უნდა მოვერიდოთ l-ის გამოყენებას, ვინაიდან იგი ადვილად შეიძლება აგვერიოს ერთიანში (1 l). კორექტული მაგალითებია: 0x7fffffffffffffffL, 9223372036854775697L, ეს long ტიპის მაქსიმალური ზომის რიცხვებია.

აღსანიშნავია, რომ მთელრიცხვა მნიშვნელობა შეიძლება მიენიჭოს char ტიპს, თუ რიცხვი იმყოფება ამ ტიპის დასაშ­ვებ დიაპაზონში.

მცოცავ მძიმიანი კონსტანტები

მცოცავ მძიმიანი კონსტანტები ჩაიწერება მხოლოდ ათო­ბი­თი თვლის სისტემაში და ესაა რიცხვები წილადი ნაწი­ლით. ისინი შეიძლება ჩაწერილი იყოს, როგორც სტანდარ­ტულ - ფიქსირებულ ფორმატში, ისე სამეცნიერო - ექსპონენ­ციალურ (მაჩვენებლიან) ფორმატში. ფიქსირებულ ფორმატ­ში ჩაწერი­ლი რიცხვი შედგება მთელი რიცხვისაგან, რომელ­საც მოყვე­ბა ათობითი წერტილი და წილადი ნაწილისაგან. მაგალითა, 2.0, 3.14159, -2.72 წარმოადგენენ სტანდარტულ ფორმატში დასაშვებ, კორექტულად ჩაწერილ რიცხვებს. სამეცნიერო ანუ ექსპონენციალური ფორმა იყენებს რიცხვის სტანდარ­ტულ, მცოცავმძიმიან ფორმას, რომელსაც ემატება სუფიქსი, რომელიც მიუთითებს 10-ის რომელ ხარისხზე უნდა გამრავლდეს რიცხვი. ექსპონენ­ციალური ფუნქციის მისათი­თებლად გამოიყენება სიმბოლო E ან e, რომლის შემდეგაც მოდის ათობითი მთელი რიცხვი (დადებითი ან უარყო­ფითი). მაგალითად, 6.022 E12, 314158 E-05, 2e+100.

სტანდარტულად ნამდვილი ტიპის კონსტანტები ინახება double ტიპის სახით. ნამდვილი ტიპის კონსტანტის ბოლოს შეიძლება ჩავწეროთ (მივუთითოთ) ასო F ან f, მაშინ კონსტანტა შენახული იქნება float ტიპის სახით. მაგალითად, 3.5f, -45.67F, 4.7e-5f. პრინციპში, შესაძლებელია ასო D ან d-ს მიწერაც, მაგალითად, -456.789d, 0.0123D, რაც მიუთითებს double ტიპს, მაგარამ იგი ზედმეტია, ვინაიდან ნამდვილი კონსტანტები ისედაც double ფორმატში ინახება.

სიმბოლური კონსტანტები

Java-ში სიმბოლოები წარმოდგენილია Unicode სტანდარ­ტში. ესაა 16 ბიტიანი მნიშვნელობა, რომელიც შეიძლება გადაყვანილი იქნას მთელ რიცხვებში, რომლებზედაც შესაძ­ლებელია მთელრიცხვა არითმეტიკული ოპერაციების, მაგა­ლითად, შეკრებისა და გამოკლების ოპერაციების ჩატარება. სიმბოლური კონსტანტები ჩაიწერება ორი ერთმაგი ბრჭყა­ლის (აპოსტროფების) შიგნით. სიმბოლოების ჩასაწერად გამოიყენება შემდეგი ფორმები:

- ASCII სტანდარტის ყველა გრაფიკული გამოსახულების მქონე სიმბოლო უშუალოდ შეიძლება ჩაიწეროს აპოს­ტრო­ფებს შორის. მაგალითად, `a`, `z`, `@`, `&`;

- იმ სიმბოლოების ასაკრებად, რომლის უშუალოდ შეტანა შეუძლებელია, მაგალითად, მმართველი სიმბოლოები­სათ­ვის, უნდა გამოვიყენოთ სპეციალური მმართველი მიმდევ­რობა, მაგალითად, `n` - ახალი სტრიქონის სიმბოლო (ASCII კოდი - 10); `t` - ჰორიზონტალური ტაბულაციის სიმ­ბოლო (ASCII კოდი - 9); `f` - ახალ ფურცელზე გადასვლის სიმბოლო (ASCII კოდი - 12); ``- შებრუ­ნე­ბუ­ლი დახრილი ხაზი;`”` - ორმაგი ბრჭყალები;``` აპოს­ტრო­ფი; სიმბოლოების მმართველი მიმდევრო­ბები ნაჩვე­ნების ცხრილ 3-ში

ცხრილი 3. მმართველი სიმბოლოების მიმდევრობები

- ნებისმიერი სიმბოლოს კოდი შეიძლება ჩავწეროთ სამ თან­რიგა რვაობითში ჩაწერილი რიცხვის სახით, რომელ­საც წინ უწერია შებრუნებული დახრილი ხაზი და მო­თავსე­ბულია აპოსტროფში. მაგალითად, `123` არის ასო S-ს კოდი. არაა რეკომენდებული ჩაწერის ამ ფორმის გამოყენება ზემოთ ჩამოთვლილი გრაფიკული გამოსა­ხუ­ლე­ბის მქონე სიმბოლოებისა და მმართავი სიმბოლოების ჩასაწერად, ვინაიდან კომპილატორი რვაობით რიცხვს მაშინვე გადაიყვანს ზემოთ მითი­თებულ ფორმაში. უდიდესი კოდია `377`, რომელიც შეესაბამება ათობით 255-ს;

- Unicode კოდირების სტანდარტში ნებისმიერი სიმბო­ლოს კო­დი ჩაიწერება აპოსტროფებში დახრილი ხაზისა და ლა­თი­ნური ასო U-ს შემდეგ ჩაწერილი ოთხი თექვსმე­ტო­ბითი ციფრით. მაგალითად, `u0053` არის ასო S-ს კოდი.

რა ფორმითაც არ უნდა იყოს ჩაწერილი სიმბოლოები, კომპი­ლა­ტორს ისინი გადაყავს Unicode-ში. ასევე Unicode-ში გადა­ყავს პროგრამის ტექსტი. Java-ს შემსრულებელი გარემო მუ­შაობს მხოლოდ Unicode კოდირებასთან.

ბულის კონსტანტები

ბულის კონსტანტების მნიშვნელობებია მხოლოდ ორი true და false. ეს მნიშვნელობები არ გარდაიქმნება არცერთ რიცხვით წარმედგენაში. ეს მნიშვნელობები Java-ში შეიძ­ლება მიენიჭოს მხოლოდ boolean-ად გამოცხადებულ ცვლა­დებს ან მონაწილეობა მიიღონ ბულის ოპერაციებიან გამოსა­ხუ­ლებებში.

სტრიქონული კონსტანტები

სტრიქონული კონსტანტების ჩაწერა Java-ში ხდება სიმბო­ლო­­ების მიმდევრობის ორმაგ ბრჭყალებში მითითებით. მაგა­ლითად, “Hello World”, “twonlines”, “”This is in quotes””.

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

Java-ში სტრიქონები უნდა იწყებოდეს და მთავრდებოდეს ერთ სტრიქონში. ენაში არ არსებობს რაიმე სიმბოლო, რომე­ლიც მიუთითებდა სტრიქონის გაგრძელებას.

ცვლადები

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

ცვლადების გამოცხადება

Java-ში ცვლადების გამოცხადება უნდა მოხდეს მის გამო­ყენებამდე. ცვლადების გამოცხადების ძირითადი ფორმა ასე შეიძლება წარმოვადგინოთ:

<ტიპი> <იდენტიფიკატორი> [=<მნიშვნელობა>] [,<იდენტიფიკატორი> [=მნიშვნელობა] ...];

<ტიპი> - აქ უნდა ჩაიწეროს კონკრეტული Java-ს ერთ-ერთი ელე­მენ­ტარული ტიპი ან კლასის სახელი ან ინტერფეისი (კლა­სებსა და ინტერფეისებს ქვემოთ განვიხილავთ).

<იდენტიფიკატორი> - აქ უნდა ჩაიწეროს ცვლადის სახელი.

ცვლადს შეიძლება თავიდანვე მივანიჭოთ საწყისი მნიშ­ვნელობა (მოვახდინოთ მისი ინიციალიზაცია) = (უდრის) ნიშნისა და კონკრეტული მნიშვნელობის მითითებით. შესაძ­ლებელია ინიციალიზაციისათვის გამოსახუ­ლების მითით­ებაც, ოღონდ მისი მნიშვნელობის ტიპი უნდა ემთხვეოდეს ცვლადის ტიპს ან დაიყვანებოდეს ამ ტიპზე.

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

int a, b, c; // გამოცხადებულია სამი int ტიპის ცვლადი: a,b,c

int d = 3, e, f = 5; // გამოცხადებულია სამი int ტიპის ცვლადი,

// ხდება d და f-ის ინიციალიზაცია

byte z = 22; // z ცვლადის ინიციალიზაცია

double pi = 3.14159; // pi ცვლადის ინიციალიზაცია

char c = `x`; // c ცვლადს ენიჭება `x`მნიშვნელობა

ამ მაგალითში გამოცხადებული იდენტიფიკატორები ძალიან მარტივია, თუმცა Java-ში დასაშვებია ნებისმიერი სწორად გაფორმებული იდენტიფიკატორი, ნებისმიერი გამოცხადე­ბული ტიპით.

ტიპების გარდაქმნა და დაყვანა

პროგრამისტებს ხშირად უწევთ ერთი ტიპის ცვლადისათვის განსხვავებული ტიპის მნიშვნელობის მინიჭება. თუ ეს ორივე ტიპი თავსებადია, Java გარდაქმნას ავტომატურად აკეთებს. მაგალითად, ყოველთვის შეიძლება int ტიპის მნიშვნელობა მიენიჭოს long ტიპის ცვლადს. მაგრამ ყველა ტიპი არაა თავსებადი, ამიტომ ავტომატური გარდაქმნაც ასეთ შემთხვევაში შეუძლებელია. მაგალითად, არ არსებობს არავითარი ავტომატური გარდაქმნის მეთოდი double-დან byte-ში. Java-ში არათავსებად ტიპებს შორის გარდაქმნა საბედნიეროდ მაინც შეიძლება. ამისათვის საჭიროა დაყვანის გამოყენება, რომელიც ახდენს არათავსებადი ტიპების ცხად გარდაქმნას.

ტიპების ავტომატური გარდაქმნა Java-ში

ცვლადზე სხვა ტიპის მნიშვნელობის მინიჭებისას ავტომა­ტური გარდაქმნა გამოიყენება შემდეგი პირობების დაცვის შემთხვევაში:

· ორივე ტიპი თავსებადია;

· რასაც ენიჭება, იმ ტიპის სიგრძე მეტია მისანიჭებელ ტიპზე.

ამ ორი პირობის დაცვისას ხდება გარდაქმნა გაფართოებით (wedenning conversion). მაგალითად, int ტიპი ყოველთვის უფრო მეტია ვიდრე byte-ს ტიპის ყველა დასაშვები მნიშ­ვნელობა, ამიტომ არაა საჭირო რაიმე ცხადი დაყვანის ოპერატორი.

გაფართოებითი გარდაქმნის თვალსაზრისით, მთელიდან მცოცავმძიმიან რიცხვით ტიპებში გარდაქმნა თავსებადია. მაგრამ არ არსებობს ავტომატური გარდაქმნა რიცხვითი ტიპებიდან char და boolean ტიპებში. char და boolean ტიპები ასევე შეუთავსებადია ერთმანეთის მიმართაც.

Java ასრულებს ტიპების ავტომატურ გარდაქმნას მთელრიც­ხვა კონსტანტის მინიჭებისას byte, short, long და char ტიპის ცვლადებზე.

არათავსებადი ტიპების დაყვანა

მართალია ავტომატური დაყვანა მოსახერხებელია, მაგრამ იგი ყველა შემთხვევაში არ მუშაობს. მაგალითად, როგორ უნდა მოხდეს გარდაქმნა int ტიპის მინიჭებისას byte ტიპზე? ასეთი ტიპის გარდაქმნას უწოდებენ გარდაქმნას შემცირე­ბით (narrowing conversion), ვინაიდან საწყისი მნიშ­ვნელობა ისე უნდა შემცირდეს, რომ იგი ჩაეტიოს მიზნობ­რივ ცვლადის ტიპში.

ორ არათავსებად ტიპს შორის გარდაქმნის განსახორციე­ლებლად საჭიროა ტიპების დაყვანა (casting). დაყვანა - ესაა ტიპების ცხადი გარდაქმნა. დაყვანის ზოგად ფორმას ასეთი სახე აქვს:

(<მიზნობრივი ტიპი>) <მნიშვნელობა>

აქ <მიზნობრივი ტიპი> განსაზღვრავს იმ ტიპს, რომელშიც უნდა გარდაიქმნას <მნიშვნელობა>. კოდის შემდეგი ფრაგ­მენტი int ტიპს დაიყვანს byte ტიპზე, იგი შემცირდება (რედუცირდება) საწყისი რიცხვის byte ტიპის დიაპაზონის მოდულზე გაყოფის ნაშთამდე (ამ შემთხვევაში 128-ზე გაყოფის ნაშთი).

int a;

byte b;

// ...

b = (byte) a;

უფრო მარტივად რომ ვთქვათ, დაყვანის პროცესის დროს ხდება ზედმეტი უფროსი ბიტების მოცილება (გადაყრა). მაგალითად,

byte b = (byte) 300;

ცვლადი b მნიშვნელობად ღებულობს 44-ს. მართლაც, რიც­ხვი 300 ორობით წარმოდგენაში ტოლია 100101100, გადავარ­დება უფროსი ბიტი და მიიღება 00101100, ეს ორობითი რიცხვი კი ათობითში 44-ია.

მთელი ტიპის ცვლადზე მცოცავმძიმიანი მნიშვნელობის მინიჭებისას ხდება სხვა სახის დაყვანა - შეკვეცა (truncation, reduction). ამ დროს მთელი ნაწილი ენიჭება ცვლადს, ხოლო წილადი ნაწილი იკარგება. მაგალითად, თუ მთელი ტიპის ცვლადს ვანიჭებთ 1.23 წილად რიცხვს, მაშინ ცვლადის მნიშვნელობა იქნება 1-ის ტოლი, ხოლო 0.23 ჩამოეჭრება. რასაკვირველია, თუ მთელი ნაწილი ძალიან დიდია, იგი რედუცირდება მთელი ტიპის დიაპაზონის მოდულამდე.

ლისტინგ ??? -ზე ნაჩვენები პროგრამა გვიჩვენებს ტიპების გარდაქმნის და დაყვანის რამდენიმე მაგალითს.

ლისტინგ ???

с1аss Conversion {

public static void main(String args[])

byte b;

int i = 257;

double d = 323.142;

Sуstеm.оut.рrintln("n int -ის გარდაქმნა byte-ში");

b = (byte) i;

System.out.print1n("i და b " + i + " " + B);

Sуstеm.оut.рrintln("n double-ს გარდაქმნა int-ში");

i = (int) d;

System.out.println("d და i " + d +" " + i);

Sуstеm.оut.рrintln("n double-ს გარდაქმნა byte-ში");

b = (byte) d;

System.out.print1n("d და b " + d + " " + B);

}

}

­ამ პროგრამის შედეგად გამოვა:

­ int -ის გარდაქმნა byte-ში

i და b 257 1

­ double-ს გარდაქმნა int-ში

d და i 323.142 323

­ double-ს გარდაქმნა byte-ში

d и b 323.142 67

გამოსახულებებში ტიპის ავტომატური ამაღლება

მინიჭების ოპერაციის გარდა გარკვეული გარდაქმნები შეიძ­ლება მოხდეს გამოსახულებების გამოთვლისას. მაგალითად

byte a = 40;

byte b = 50;

byte c = 100;

int d = a * b / c;

შუალედური გამოთვლის შედეგი a * b შეიძლება გავიდეს byte-ს ტიპის დასაშვები დიაპაზონის საზღვრებს გარეთ. ასეთი პრობლემების გადასაწყვეტად Java-ში გამოსახუ­ლე­ბების გამოთვლისას ხდება ყოველი byte და short ოპერანდის ავტომატურად ამაღლდება int-მდე. ანუ შუალედური გამოსახულების გამოთვლა ხდება მთელრიც­ხვა მნიშვნე­ლობებით და არა ბაიტებით. შუალედური გამოსახულება იქნება 50*40, რომლის შედეგია 2000, რაც დასაშვებია, მიუხედავად იმისა, რომ a და b ცვლადები byte ტიპისაა.

მიუხედავად იმისა, რომ ავტომატური ამაღლება მოსახერ­ხებელია, მას ზოგჯერ მივყავართ კომპილაციის დროს შეც­დომებამდე. მაგალითად, გარეგნულად კორექტული კოდი იწვევს კომპილაციის შეცდომას:

byte b = 50;

b = b * 2; // შეცდომა! int ტიპის მნიშვნელობა

// ენიჭება byte ტიპის ცვლადს!

ასეთ შემთხვევაში გამოყენებული უნდა იქნას ტიპების ცხა­დი დაყვანა:

byte b = 50;

b = (byte) (b * 2);

Java-ში მოქმედებს

ტიპის ამაღლების რამდენიმე წესი:

1. byte, short და char მნიშვნელობები ამაღლდება int ტიპამ­დე;

2. თუ ერთი ოპერანდის ტიპია long, მთლიანი გამოსახუ­ლე­ბის ტიპი ამაღლდება long-მდე;

3. თუ ერთი ოპერანდი float-ის ტიპისაა, მთლიანი გამოსა­ხუ­ლების ტიპი ამაღლდება float-მდე;

4. თუ ნებისმიერი ოპერანდი double-ის ტიპისაა, მთლიანი გამო­სახულების ტიპი ამაღლდება double-მდე.

Share this post


Link to post
Share on other sites

მასივები

მასივი ესაა ერთი ტიპის მონაცემების ერთობლიობა, რომლე­ბზე მიმართვა ხდება ერთი, საერთო სახელის საშუ­ალებით. Java-ში დაშვებულია, როგორც ერთგანზომი­ლე­ბიანი, ისე მრავალგანზომილებიანი ნებისმიერი ტიპის მასი­ვების გამოც­ხადება. მასივის კონკრეტულ ელემენტზე მიმარ­თვა ხდება მისი ინდექსის მიხედვით.

ერთგანზომილებიანი მასივები

ერთგანზომილებიანი მასივი წარმოადგენს ერთი ტიპის ცვლადების სიას. მასივის შესაქმნელად, ჯერ უნდა შეიქმნას საჭირო ტიპის მასივის ცვლადი. ერთგანზომილებიანი მასივის გამოცხადების ზოგადი ფორმაა:

<ტიპი> <მასივის სახელი>[];

აქ <ტიპი> წარმოადგენს მასივის შემადგენელი ელემენტების ტიპს. მაგალითად, შემდეგი ოპერატორით ხდება monthDays მასივის გამოცხადება, რომლის ელემენტები int ტიპისაა:

int monthDays[];

ამ გამოცხადებით ჯერ მასივი არ შექმნილა. monthDays მასივის ფაქტიური მნიშვნელობა ჯერჯერობით არის null, რომელიც წარმოადგენს მასივს მნიშვნელობის გარეშე. monthDays მასივის ცვლადის რეალური ფიზიკური მთელი რიცხვების მასივთან დასაკავშირებლად საჭიროა ოპერაციით new მეხსიერების გამოყოფა და მისი მისამართის მინიჭება ამ ცვლადზე. მომავალში ჩვენ ამ ოპერატორს უფრო დაწვრი­ლებით განვიხილავთ, ახლა კი აღვნიშნავთ, რომ მისი ზოგა­დი ფორმა ასეთია:

<მასივის სახელი> = new <ტიპი>[<ზომა>] ;

<ტიპი> აღწერს დარეზერვირებული მონაცემების მეხსიე­რების ტიპს. <ზომა> მიუთითებს მასივში ელემენტების რაოდენობას, ხოლო <მასივის ცვლადი> მასივთან დაკავში­რებული ცვლადია. ანუ, new ოპრაციით მეხსიერების გამოსა­ყოფად საჭიროა ელემენტების ტიპისა და რაოდენობის მითითება. მასივის ელემენტებისათვის new ოპრაციით გამოყოფილი მეხსიერების ინიციალიზაცია მოხდება ნულო­ვანი მნიშვნელობებით. ჩვენ მაგალითში ხდება 12 ელემენ­ტიანი მასივისათვის მეხსიერების რეზერ­ვირება და მისი დაკავშირება monthDays მასივის სახელთან.

monthDays = new int[12];

ამრიგად, მასივის შექმნა ორსაფეხურიანი პროცესია. ჯერ ცხადდება საჭირო ტიპის მასივის ცვლადი, ხოლო შემდეგ, new ოპერაციით გამოიყოფა მასივის შესანახი მეხსიერება და მისი მისამართი ენიჭება მასივის ცვლადს. ამრიგად Java-ში ყველა მასივი დინამიურად იქმნება.

მასივის გამოცხადებისა და შექმნის შემდეგ შესაძლებელია მის თითოეულ ელემენტს მივმართოდ ინდექსით, რომელიც კვადრატულ ფრჩხილებში იქნება მოთავსებული. მასივის ინ­დექ­სი იწყება 0-დან. მაგალითად, შემდეგი ოპერატორი monthDays მასივის მეორე ელემენტს ანიჭებს მნიშვნელობად 28-ს.

monthDays [1] = 28;

შემდეგი კოდის სტრიქონი ასახავს იმ ელემენტის მნიშვნე­ლო­ბას, რომელიც იმყოფება 3-ე ინდექსიან ელემენტად:

System.out.println(monthDays[3]);

მთელი პროცესის სადემონსტრაციოდ, ლისტინგი ??? ჩაწე­რილია პროგრამა, რომელიც ქმნის წლის ყოველი თვის დღე­ე­ბის რაოდენობის მასივს.

class Array {

public static void main(String args[]){

int monthDays[];

monthDays = new int[12];

monthDays[0] = 31;

monthDays[1] = 28;

monthDays[2] = 31;

monthDays[3] = 30;

monthDays[4] = 31;

monthDays[5] = 30;

monthDays[6] = 31;

monthDays[7] = 31;

monthDays[8] = 30;

monthDays[9] = 31;

monthDays[10] = 30;

monthDays[11] = 31;

System.out.println (“აპრილში არის ”+ monthDays[3] + “დღე”);

}

}

ამ პროგრამის შესრულებით კონსოლზე გამოვა აპრილში დღეების რაოდენობა.

მასივის ცვლადის გამოცხადება შეიძლება გავაერთიანოთ მისთვის მეხსიერების გამოყოფასთან:

int monthDays[] = new int[12];

ასევე შესაძლებელია მასივის ინიციალიზაცია მისი გამოცხ­ადებისას. ეს პროცესი ჰგავს ცვლადის ინიციალიზა­ციის პრო­ცესს. მასივის ინიციალიზატორი ესაა ერთმა­ნეთისაგან მძიმით დაშორებული გამოსახულებების სია, რომელიც ფი­გუ­რულ ფრჩხილებშია მოთავსებული. მძიმით გამოყო­ფილია მასივის ელემენტების მნიშვნელობები. მასივი ავტო­მატურად იქმნება ისეთი ზომის, რომ მასში ჩაეტიოს ინიციალიზატორში მითითებული ყველა ელემენტი. ამ დროს new ოპერატორის გამოყენება საჭირო არაა. წინა მაგალითის პროგრამის ფრაგმენტი ასე შეიძლება ჩავწეროთ:

class AutoArray {

public static void main(String args[]){

int monthDays[];

monthDays = {31,28,31,30,31,30,31,31,30,31,30,31};

System.out.println (“აპრილში არის ”+ monthDays[3] + “დღე”);

}

}

Java-ს შემსრულებელი გარემო გულდასმით ამოწმებს, ხომ არ მოხდა შენახვის ან მიმართვის მცდელობა ისეთ ინდექსზე, რომელიც გადის მასივის დასაშვები დიაპაზონის გარეთ. მაგალითად, ჩვენი მაგალითის შემთხვევაში შემსრულებელი გარემო ამოწმებს ინდექსი იმყოფება თუ არა 0 – 11 დიაპა­ზონში. ამ დიაპაზონის გარეთ მიმართვის მცდე­ლობა შესრუ­ლების პროცესში იწვევს შეცდომას.

მრავალგანზომილებიანი მასივები

Java-ს მრავალგანზომილებიანი მასივი წარმოადგენს მასი­ვების მასივს. ისინი მოქმედებენ ჩვეულებრივი მრავალგან­ზომილებიანი მასივის ანალოგიურად. თუმცა მათ გარკვე­ული თავისებურაბაც ახასიათებთ. მრავალგანზომი­ლებიანი მასივის თითოეული დამატებითი ინდექსის მისათითებლად იყენებენ კვადრატული ფრჩხილების ცალკე წყვილს. მაგა­ლი­თად, ორგანზომილებიანი მასივი შეიძლება გამოვაც­ხადოთ ასე:

int twoD[][] = new int[4][5];

ეს ოპერატორი გამოჰყოფს მეხსიერებას 4x5 განზომილებიანი მასივისათვის. მასივის ლოგიკური ორგანიზება ნაჩვენებია სურ. 4-ზე

7ade62ef2954.jpg

სურ. 4. ორგანზომილებიანი მასივის ლოგიკური წარმოდგენა

მრავალგანზომილებიანი მასივისათვის მეხსიერების გამო­საყოფად ჯერ საჭიროა მივუთითოდ მეხსიერება მხოლოდ პირველი (მარცხენა) განზომილებისათვის. ყოველი შემდეგი განზომილებისათვის მეხსიერება შეიძლება გამოვყოთ ცალ­კე. მაგალითად, შემდეგი კოდი არეზერვი­რებს მეხსიერებას twoD მასივის გამოცხადებისას პირველი განზომილე­ბისათ­ვის. მეორე განზომილებისათვის მეხსი­ერე­ბის გამოყოფა ხდება ხელით, ცალცალკე.

int twoD [] [] ­= new int [4] [] ;

twoD[0] =­ new int[5];

twoD[1] =­ new int[5];

twoD[2] =­ new int[5];

twoD[3] ­= new int[5];

მართალია ამ შემთხვევაში მეორე განზომილებისათვის ცალ­კე მეხსიერების გამოყოფა არ იძლევა რაიმე უპირა­ტესობას, მაგრამ სხვა სიტუაციაში ეს შეიძლება სასარგებლო გამოდ­გეს. მაგალითად, მეხსიერების ხელით გამოყოფისას არაა აუცილებელი თითოეული განზომილე­ბისათვის ერთნაირი ზომა მივუთითოდ. ამრიგად, პროგრამისტი თვითონ მარ­თავს მასივის თითოეული განზომილების სიგრძეს.

მაგალითად, შემდეგი პროგრამა ქმნის ორგანზომილებიან მასივს, მეორე განზომილების სხვადასხვა ზომებით.

class TwoDAgain {

public static void main(String args[]) {

int twoD[][] = ­new int[4][];

twoD[0] = new int[1];

twoD[l] = new int[2];

twoD[2] = new int[3];

twoD[3] = new int[4];

}

}

შექმნილ მასივს ექნება შემდეგი სახე (სურ 3.2):

3776facd52d6.jpg

სურ. 5. ორგანზომილებიანი მასივი, რომლის მეორე განზო­მილება სხვადასხვა ზომისაა

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

class Matrix {

public static void main(String args[]) {

double m[] [] ­= {

{ 0*0, 1*0, 2*0, 3*0 },

{ 0*1, 1*1, 2*1, 3*1 },

{ 0*2, 1*2, 2*2, 3*2 },

{ 0*3, 1*3, 2*3, 3*3 }

­ } ;

}

}

მასივების გამოცხადების ალტერნატიული ფორმა

მასივების გამოცხადებისათვის შეიძლება გამოყენებული იქ­ნას მეორე ფორმა:

<ტიპი> [] <ცვლადის სახელი>;

ამ ფორმაში კვადრატული ფრჩხილები მიეთითება ტიპის გამოცხადების შემდეგ და არა მასივის ცვლადის შემდეგ. მაგალითად, შემდეგი ორი გამოცხადება ეკვივალენ­ტურია:

int al[] =­ new int[З];

int[] а1=­ new int[З];

ქვემოთ ნაჩვენები ორი გამოცხადებაც ეკვივალენტურია:

char twod1[] [] =­ new сhаr[З] [4];

char[] [] twod1 =­ new сhаr[З] [4];

გამოცხადების ეს მეორე ფორმა მოსახერხებელია, როდესაც ხდება რამდენიმე მასივის ერთდროული გამოცხადება. მაგალითად, გამოცხადება

int[] nums, nums2, numsЗ; // იქმნება 3 მასივი

ქმნის int ტიპის მასივების სამ სახელს. იგი ეკვივალენტურია შემდეგი გამოცხადების

int nums[], nums2[], numsЗ[]; // იქმნება 3 მასივი

ეს ალტერნატიული ფორმა ასევე მოსახერხებელია, როდესაც მასივი ცხადდება მეთოდის დაბრუნების ტიპად.

ოპერაციები

Java-ში შეიძლება გამოვყოთ ოპერაციების 4 ძირითადი ჯგუფი: არითმეტიკული ოპერაციები, ბიტური ოპერაციები, შედარების ოპერაციები და ლოგიკური ოპერაციები. არსე­ბობს კიდევ სხვა დამატებითი ოპერაციებიც, რომლებიც გან­სა­კუთრებულ სიტუაციაში გამოიყენება.

არითმეტიკული ოპერაციები

არითმეტიკული ოპერაციები ისევე გამოიყენება მათემატი­კურ გამოსახულებებში, როგორც ამას ვაკეთებთ ალგებრაში. ცხრილ 4-ში ჩამოთვლილია არითმეტიკული ოპეარაციები

ცხრილი 4. არითმეტიკული ოპერაციები

ოპერაცია

აღწერა

+

შეკრება

-

გამოკლება

*

გამრავლება

/

გაყოფა

%

მოდულით გაყოფა

++

ინკრემენტი

+=

ავტოასოციური შეკრება (შეკრება მინიჭებით)

-=

ავტოასოციური გამოკლება (გამოკლება მინიჭებით)

*=

ავტოასოციური გამრავლება (გამრავლება მინიჭებით)

/=

ავტოასოციური გაყოფა (გაყოფა მონიჭებით)

%=

ავტოასოციური მოდულით გაყოფა (გაყოფა მინიჭებით)

– –

დეკრიმენტი

არითმეტიკული ოპერაციების ოპერანდების ტიპი უნდა იყოს რიცხვითი. არითმეტიკული ოპერაციების ჩატარება არ შეიძლება boolean ტიპის ცვლადებზე, მაგრამ შესაძლებელია char ტიპთან, ვინაიდან Java-ში ეს ტიპი, ფაქტიურად int ტიპის ქვესიმრავლეა.

ძირითადი არითმეტიკული ოპერაციები

ყველა ძირითადი ოპერაცია - შეკრება, გამოკლება, გამრავ­ლე­ბა და გაყოფა რიცხვით ტიპებთან მოქმედებენ ისე, როგორც ალგებრაში. გამოკლების ოპერაციას ასევე აქვს უნარული (ერთ ოპერანდიანი) ფორმა, რომელიც ნიშანს უცვლის მის ერთადერთ ოპერანდს. უნდა გვახსოვდეს, რომ მთელრიცხვა ტიპზე გაყოფის ოპერაციის გამოყენებისას განაყოფს არ ექნება წილადი ნაწილი.

შემდეგი მარტივი პროგრამა დემონსტრირებას უკეთებს არითმეტიკულ ოპერაციებს (ლისტინგი ??). აქ დემონსტრი­რებულია განსხვავება მთერიცხვა გაყოფასა და მცოცავ­მძიმიან გაყოფას შორის.

class BasicMath {

public static void main(String args[]) {

// მთელრიცხვა არითმეტიკული ოპერაციები

Sуstеm.оut.рrintln("მთელრიცხვა არითმეტიკა");

int а =­ 1 + 1;

int b = ­ а * 3;

int с ­= b / 4;

int d =­ с -­ а;

int е ­= -­d;

System.out.println("a =­ " + а);

System.out.println("b ­= " + B);

System.out.println("c ­= " + с);

System.out.println("d =­"+ d);

System.out.println("e ­ =" + е);

// double ტიპზე არითმეტიკული ოპერაციები

Sуstеm.оut.рriпtlп("n მცოცავმძიმიანი არითმეტიკა");

double da = 1 + 1;

double db ­= da * 3;

double dc =­ db / 4;

double dd =­ dc -­ а;

double de = -­dd;

System.out.println("da = "+ da);

System.out.println("db = "+ db);

System.out.println("dc ­= " + dc);

System.out.println("dd ­= " + dd);

System.out.println("de =­ " + de);

}

}

ამ პროგრამის შესრულების შედეგად კონსოლზე გამოვა ასეთი შედეგი:

მთელრიცხვა არითმეტიკა

а = 2

b =­ 6

с =­ 1

d ­= ­1

е =­ 1

მცოცავმძიმიანი არითმეტიკა

da =­ 2.0

db =­ 6.0

dc =­ 1.5

dd =­ ­0.5

de = ­0. 5

როგორც მაგალითიდან ნახეთ მთელი რიცხვების გაყოფისას შედეგად ისევ მთელი რიცხვი მიიღება, ამიტომ მას ხშირად „მთელ გაყოფას“ უწოდებენ. მაგალითად, 5/2 შედეგად იძლევა 2-ს და არა 2.5, ხოლო 5/(-3) შედეგია -1. წილადი ნაწილი უბრალოდ ვარდება.

მათემატიკისათვის ეს უცნაური წესი ბუნებრივია პროგრამირებაში: თუ ორივე ოპერანდს ერთიდაიგივე ტიპი აქვთ, მაშინ შედეგსაც იგივე ტიპი აქვს. საკმარისია დაიწეროს 5/2.0 ან 5.0/2 ან 5.0/2.0 მაშინ მივიღებთ ნამდვილი რიცხვების გაყოფას და შედეგი იქნება 2.5.

მოდულით გაყოფის (ნაშთის) ოპერაცია

მოდულით გაყოფის ანუ ნაშთის გამოთვლის ოპერაცია % აბრუნებს გაყოფის ოპერაციის ნაშთს. ეს ოპერაცია შეიძლება გამოყენებული იქნას როგორც მთელ ტიპებზე, ისე მცოცავ­მძიმიან რიცხვებზე. შემდეგ პროგრამაში დემონსტრირე­ბუ­ლია % ოპერაციის გამოყენება

c1ass Modu1us {

public static void main(String args[]) {

int х ­ 42;

double у =­ 42.25;

­ System.out.print1n("x mod 10 ="+х % 10);

System.out.print1n("у mod 10 ="+у % 10);

}

}

პროგრამის შესრულების შედეგია:

х mod 10 =­ 2

y mod 10­ = 2.25

მოდულით გაყოფის ოპერაცია ზოგადად ასე შეიძლება ჩავწეროთ:

a % b = a – (a / B) * b

მაგალითად, 5 % 2 შედეგად მოგვცემს 1 , ხოლო 5 % (-3) მოგვცემს 2 , ვინაიდან 5-(5/(-3))*(-3)=5-(-1)*(-3)=5-3=2 . ასევე (-5)%3 შედეგად იქნება -2 , ვინაიდან (-5)-((-5)/3)*3=-5-(-1*3)=-5+3=-2 .

­ ავტოასოციური ოპერაციები

Java-ში არსებობს სპეციალური ოპერაციები, რომლებიც წარ­მოადგენენ არითმეტიკული და მინიჭების ოპრაციის გაერ­თიანებას. პროგრამირებაში ხშირად გვხვდება ამდაგვა­რი ოპერატორები:

a = a + 4;

Java-ში ეს ოპერატორი შეიძლება ასე ჩაიწეროს

a += 4;

ოპერატორის ამ ვერსიაში გამოყენებულია ავტოასოციური ოპერაცია +=. ორივე ეს ოპერაცია ერთიდაიგივე მოქმედებას აკეთებს: ცვლადის მნიშვნელობას ზრდის 4-ით.

მეორე მაგალითი:

a = a % 2;

რომელიც ასე შეიძლება ჩაიწეროს:

a %= 2;

ამ შემთხვევაში %= ოპერაცია გამოითვლის ნაშთს და შედეგს მიანიჭებს ისევ a ცვლადს.

ავტოასოციური ოპერაციები არსებობს ყველა ორ ოპერან­დიანი არითმეტიკული ოპერაციებისათვის. ამრიგად, ყველა ოპერატორი, რომელსაც აქვს ასეთი ფორმა

<ცვლადი> = <ცვლადი> <ოპერაცია> <გამოსახულება>;

შეიძლება ჩაიწეროს ასე

<ცვლადი> <ოპერაცია>= გამოსახულება;

ავტოასოციური ოპერაციები ორ უპირატესობას იძლევა:

1. იგი ამცირებს შესატანი კოდის მოცულობას, ვინაიდან წარმოადგენს გრძელი ფორმის ერთგვარ „შემოკლებულ“ ფორმას;

2. შემსრულებელ გარემოში მათი რეალიზაცია უფრო ეფექტურია, ვიდრე მისი ეკვივალენტური გრძელი ფორმის.

ამ მიზეზების გამო პროფესიონალურად შედგენილ Java პროგ­რამებში ავტოასოციური ოპერაციები ძალიან ხშირად გვხვდება.

მაგალითი:

class OpEquals {

public static void main(String args[])

int а =­ 1;

int b = ­2;

int с ­= 3;

а +=­ 5;

b *=­ 4;

с +=­ а * b;

с %= 6;

System.out.println("a = ­ " + а);

System.out.println("b = ­"+ B);

System.out.println("c ­= " + c);

}

}

­პროგრამის შესრულების შედეგია:

а ­= 6

b =­ 8

с =­ 3

ინკრემენტი და დეკრემენტი

ოპერაცია ინკრემენტი აღინიშნება ასე: ++ , ხოლო დეკრემენტი აღინიშნება ასე: -- .

ინკრემენტის ოპერაცია ოპერანდის მნიშვნელობას ზრდის ერთით, ხოლო დეკრემენტი ამცირებს ერთით. მაგალითად, ოპერატორი

x = x + 1;

ინკრემენტის ოპერაციით ასე ჩაიწერება:

x++;

ანალოგიურად, ოპერატორი

x = x – 1;

ეკვივალენტურია შემდეგი ოპერატორის:

x--;

ეს ოპერატორები შეიძლება ჩაიწეროს, როგორც პოსტფიქ­ტუ­რი ფორმით, როდესაც ოპერაციის სიმბოლო ჩაიწერება ოპე­რან­დის შემდეგ, ისე პრეფიქსული ფორმით, ამ დროს ოპე­რან­დი წინ უსწრებს ოპერანდს. ზემოთ მოყვანილ მაგა­ლით­ში ნებისმიერი ამ ფორმის გამოყენება ტოლფასია და ამიტომ არ აქვს მნიშვნელობა რომელს გამოვიყენებთ. მაგრამ, რო­დე­საც ინკრემენტის/დეკრემენტის ოპერაცია წარმოადგენს სხვა უფრო რთული გამოსახულების ნაწილს, მაშინ მჟღავნდება მისი ჩაწერის ფორმის განსხვავება. პრეფიქსულ ფორმაში ოპე­რან­დის მნიშვნელობა იზრდება ან მცირდება მნიშვნე­ლობის გამოსახულებაში გამოყენებამდე. პოსტფიქსურ ფორ­მაში ოპერანდის მნიშვნელობა ჯერ გამოიყენება გამოსა­ხუ­ლების გამოთვლაში, ხოლო ამის შემდეგ ოპერანდის მნიშვნელობა იცლება (იზრდება ან მცირდება იმისდა მიხედ­ვით ++ თუ -- მითითებული). მაგალითად:

x = 25;

y = ++x;

ამ შემთხვევაში y-ის მნიშვნელობა გახდება 26, როგორც მოსალოდნელო იყო, ვინაიდან ოპერანდის მნიშვნელობის ერ­თით გაზრდა ხდება მანამ, სანამ y-ს მიენიჭება x-ის მნიშ­ვნე­ლობა. ამრიგად, y = ++x; სტრიქონი ეკვივალენტურია შემ­დე­გი ორი სტრიქონის:

x = x + 1;

y = x;

მაგრამ თუ ოპერატორებს ჩავწერთ ასე:

x = 25;

y = x++;

მაშინ, x ცვლადის მნიშვნელობა ამოიღება ინკრემენტის ოპერა­ციის შესრულებამდე, ამიტომ y ცვლადის მნიშვნე­ლო­ბა ტოლი იქნება 25-ის. ცხადია, ორივე შემთხვევაში x ცვლა­დის მნიშვნელობა ერთით იზრდება იქნება 26-ის ტოლი. შესაბამისად y = x++; სტრიქონის მნიშვნელობა ეკვივა­ლენ­ტუ­რი შემდეგი ორი სტრიქონის:

y = x;

x = x + 1;

შემდეგ პროგრამაში დემონსტრირებულია ინკრემენტის ოპერაციის გამოყენება

// ++ operaciis demonstrireba.

c1ass IncDec {

public static void main(String args[])

int а =­ 1;

int b = ­2;

int с;

int d;

с =­ ++b;

d =­ а++;

с++;

System.out.println("a ­= " + а);

System.oиt.println("b ­= " + B);

System.out.println("c ­= " + с);

System.out.println("d ­= " + d);

}

}

­ამ პროგრამის შედეგად კონსოლზე გამოვა:

а =­ 2

b ­= 3

с ­= 4

d =­ 1

Share this post


Link to post
Share on other sites
Guest Ghost

http://javarush.ru/user/reference/a882582e-8619-4cdb-8d5c-90a5b0a4b2e2 java-ს შესწავლა ძაან მაგარი კირსია გირჩევთ ყველას (მხოლოდ ამ ლონკზე გადადით თორემ ისე ფაიანია და თუ ვიღაც მოგიწვევს მაგ შემთხვევაშია უფასო :) )

Share this post


Link to post
Share on other sites

არ ჯობია პირდაპირ ვორდის დოკუმენტი დადო? რა თქმა უნდა ვაფასებ შრომას და საწინააღმდეგო არც არაფერი მაქვს, უბრალოდ ასე ცოტათი მოუხერხებელი მეჩვენება :/ 

Edited by BOBOKHA

Share this post


Link to post
Share on other sites
Guest
You are commenting as a guest. If you have an account, please sign in.
გამოეხმაურეთ

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×