Inner Class-ები Java-ში

Inner Class არის კლასი, რომელიც განსაზღვრულია სხვა კლასის შიგნით. ისმის კითხვა, თუ რატომ შეიძლება მოგვინდეს ამისი გაკეთება. ამისთვის არსებობს სამი მიზეზი:

  • Inner Class-ის მეთოდებს შეუძლიათ მიწვდნენ მონაცემებს (data) იმ მხედველობის არიდან (scope), რომელშიც თვითონ არიან განსაზღვრულნი. იმ მონაცემის ჩათვითაც, რომელიც შეიძლება სხვა კლასისთვის მიუწვდომელი (private) იყოს.
  • Inner Class-ები შეიძლება დამალული (hidden) იყოს სხვა კლასებისგან იმავე პაკეტში.
  • Anonymous Inner Class-ები არის მოსახერხებელი როცა გვინდა განვსაზღვროთ callback-ები ბევრი კოდის წერის გარეშე.

 

სინტაქსი Inner Class -თვის არის საკმაორდ კომპლექსური. განვიხილოთ ისეთი Inner Class-ი, რომელიც წვდება ობიექტის state-ს. გვაქვს TalkingClock კლასი, რომელსაც აქვს ორი ველი, ერთი Integer ტიპის interval და მეორე Boolean ტიპის beep. ასევე გვაქვს ამ კლასისთვის ორპარამეტრიანი კონსტრუქტორი და ამ კლასის შიგნით გვაქვს TimePrinter კლასი, რომელიც არის Inner Class. 

1

 

განხილულ კოდში უჩვეულო ის არის, რომ TimePriner კლასს არ აქვს არც instance ველი და არც ცვლადი სახელად beep. beep–ი მიუთითებს TalkingClock-ის იმ ობიექტის ველზე, რომელმაც შექმნა TimePrinter-ი. სწორედ აქ არის Inner Class-ის ის უპირატესობა, რომ მას შეუძლია მიწვდეს როგორც თავის ველებს, ასევე outer (ის კლასი რომელშიც არის Inner Class) კლასის ველებს. ანუ Inner Class-ის ობიექტს ყოველთვის აქვს არაცხადი მიმთითებელი იმ ობიექტზე, რომელმაც შექმნა ეს Inner Class-ი. აქვე უნდა ითქვას ის, რომ კომპილერი მოდიფიცირებას უკეთებს ყველა Inner Class-ის კონსტრუქტორს და ამატებს მას ერთ პარამეტრს outer კლასის reference-თვის. ჩვენს შემთხცვევაში TimePrinter კლასს არ აქვს კონსტრუქტორი, ამიტომ კომპილერმა მისი უპარამეტრო (default) კონსტრუქტორი გარდაქმა ერთპარამეტრიან კონსტრუქტორად, რომელსაც აქვს შემდეგი სახე

public  TimePrinter (TalkingClock clock) {

          outer = clock;  // outer არის მიმთითებელი, რომელიც მიუთითებს outer კლასზე

}

outer ი არ არის Java-ს keyword-ი. ჩვენ ის გამოვიყენეთ იმიტომ ,რომ დაგვენახა ის მექანიზმი, თუ როგორ მუშაობს Inner Class-ი.

 

განვიხილოთ სპეციალური სინტაქის წესები Inner Class-თვის. წინა მაგალითში, Inner Class-ის outer კლასის მიმთითებელი (reference) აღვნიშნეთ, როგორც outer. რეალურად, outer-ის მიმთითებლის მისაღებად სინტაქსი არის შედარებით კომპლექსური. OuterClass.this არის Inner Class-ის შემქმნელი outer კლასის მიმთითებელი. მაგალითად, TimePrinter კლასის showServerTime() მეთოდის შეიძლება ასე დაგვეწერა :

2

 

ხოლო, ჩვენ თუ გვინდა დავწეროთ Inner Class-ის კონსტრუქტორი უფრო ცხადად, უნდა გამოვიყენოთ შემდეგი სინტაქსი  : outerObject.new InnerClass(constructor parameters).

მოდით, შევქმნათ main ფუნქცია TalkingClock კლასში და შევქმნათ Inner Class-ის ანუ TimePrinter-ის ობიექტი.

3

 

ეს არის main ფუნქცია, სადაც შევქმენით TimePrinter-ის ობიექტი.

Inner Class-ის სინტაქსი, რომ რთულია ამაზე არავინ დავობს. მოგვიანებით ჩვენ განვიხილავთ anonymous inner class-ებს და დავრწმუნდებით Inner Class-ების სირთულეში. რატომ არის რთული ? ჩვენთვის არ არის ცხადი, როგორ ურთიერთობენ Inner Class-ები ენის( ჯავას) ისეთ feature-ებთან როგორიცაა უსაფრთხოება და access control-ი.

უნდა აღინიშნოს ის, რომ Inner Class-ები არის არა JVM-ის მოვლენა, არამედ კომპილერის. Inner Class-ები გადაითარგმნება (ტრანსლირდება) რეგულარულ .class ფაილებად, რომელშიც outer და inner კლასების სახელები გამოიყოფა $ (დოლარის ნიშნით) და JVM-ს არ აქვს არანაირი ცოდნა (ინფორმაცია) მათ შესახებ. მაგალითად, TimePrinter კლასი TalkingClock კლასის შიგნით, გადაითარგმნება .class ფაილში , როგორც TalkingClock$TimePrinter.class . 

4

 

გთავაზობთ ზემოთ დაწერილი საილუსტრაციო პროგრამის .class ფაილებს.

 

რაც შეეხება ლოკალურ Inner Class-ებს , ესენი არის კლასები, რომლებიც იქმნება რომელიმე კონკრეტულ მეთოდში. წინა კოდი რომ განვიხილოთ, მაგალითად TalkingClock კლასს აქვს მეთოდი run() და ჩვენ გვჭრდება ამ კლასში TimePrinter  კლასი. მაშინ ჩვენ შევქმნით ლოკალურ Inner Class-ს. მოდით ვნახოთ ამის მაგალითიც:

5

 

დავიმახსოვროთ, რომ ლოკალურ Inner Class-ებს არასდროს ეწერება წვდომის მოდიფიკატორი (public ან private). მათი მხედველობის არე (scope) არის ყოველთვის იმ ბლოკში, რომელშიც არის გამოცხადებული. ლოკალური Inner Class-ის უპირატესობა არის ის, რომ ის არ არის წვდომადი გარედან. მაგალითად run() მეთოდის გარდა არაცინ ფლობს ინფორმაციას ამ TimePrinter კლასის შესახებ.

ლოკალური კლასების კიდევ ერთი უპირატესობა არის ის, რომ მათ არამარტო თავისი outer კლასის ველებზე (field) აქვთ წვდომა, არამედ მათ აქვთ წვდომა ლოკალურ ცვლადებზე. ზოგჯერ ეს ლოკალური ცვლადები უნდა იყოს final-ი. მოდით interval და beep პარამეტრები TalkingClock კლასის კონსტრუქტორიდან გადავიტანოთ run() მეთოდის პატამეტრებად.

6

 

Inner Class-ების ერთ-ერთი სახე არის anonymous inner class-ები. როცა ჩვენ ვიყენებთ ლოკალურ Inner Class-ებს, გვინდა  რომ ერთი ნაბიჯით წინ წავიწიოთ. როცა ჩვენ გვინდა, რომ შევქმნათ Inner Class-ის მხოლოდ ერთი ობიექტი, ჩვენ არ გვჭირდება ამ კლასს დავარქვათ სახელი. მსგავსს კლასს, რომელიც არის Inner Class და არ აქვს სახელი ეწოდება anonymous inner class. მოდით ვნახოთ მისი მაგალითი:

7

 

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

new superType (constructor parameters)

{

// inner class methods and data

}

აქ , superType შეიძლება იყოს ინტერფეისიც, როგორც ეს მაგალითში განვიხილეთ. თუ ინტერფეისი წერია, მაშინ ჩვენი inner class იმპლემენტაციას უკეთებს ამ ინტერფეისს, ხოლო თუ superType არის კლასი, მაშინ ჩვენი კლასი არის ამ კლასის მემკვიდრე (ანუ ჩვენი კლასი extend-ს უკეთებს superType-ს).  დავიმახსოვროთ, რომ anonymous inner class-ს არ შეიძლება ჰქონდეს კონსტრუქტორი, რადგან კონსტრუქტორის სახელი უნდა ემთხვეოდეს კლასის სახელს, ხოლო ამ ტიპის კლასებს არ აქვთ სახელი.

Person person = new Person(“MARY”);  // a Person Object

Person person = new Person(“MARY”) { … }; // an object of an inner class extending  

         Person

ხშირად ჩვენ გვინდა, რომ დავმალოთ (hide) inner class-ი სხვა კლასის შიგნით, მაგრამ არ გვჭირდებოდეს გვქონდეს მიმთთებელი outer კლასის ობიექტზე. ჩვენ შეგვიძლია აღვკვეთოთ ამ მიმთითებლის ქონა იმით, რომ გამოვაცხადოთ Inner Class-ი როგორც static (სტატიკური).

მოდით განვიხილოთ მაგალითი სტატიკური inner class-ის.

8

 

მაგალითში განხილულია ის, თუ როგორ შეიძლება შევქმნათ static inner class-ის ობიექტი. ზოგადი სინტაქსი სტატიკური inner class-ის ობიექტის შექმნისა ასეთია:

OuterClass.InnerClass innerObj = new OuterClass.InnerClass();

Leave a Reply / უპასუხე

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / შეცვლა )

Twitter picture

You are commenting using your Twitter account. Log Out / შეცვლა )

Facebook photo

You are commenting using your Facebook account. Log Out / შეცვლა )

Google+ photo

You are commenting using your Google+ account. Log Out / შეცვლა )

Connecting to %s