Java: აბსტრაქტული კლასები

განსხვავებით ჩვეულებრივი Java – ს კლასისგან აბსტრაქტრული კლასის ინსტანციაცია(კლასის ობიექტის შექმნა) შეუძლებელია. თავად Sun Microsystems – ის დოკუმენტაციაში აბსტრაქტული კლასის განმარტება დაახლოვებით ჟღერს შემდეგნაირად:

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

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

იგივე Sun Microsystems – ის დოკუმენტაციაში აბსტრაქტული მეთოდის განმარტება ასეთია:

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

აბსტრაქტული კლასი, აბსტრაქტული მეთოდით აღიწერება შემედეგნაირად:

1
2
3
4
5
6
7
8
//აბსტრაქტულ კლასს აუცილებლად ეთითება abstract მოდიფიკატორი
abstract class MyAbstractClass {
       
        //აბსტრაქტულ მეთოდს აუცილებლად ეთითება abstract მოდიფიკატორი 
        //აბსტრაქტული მეთოდი მთავრდება წერტილმძიმით ; ნაცვლად {}
  public abstract void myMethod();
 
}

მოყვანილ მაგალითში ყურადღებას იმსახურებს ორი დეტალი, ესენია: 1)abstract მოდიფიკატორი, რომელიც აუცილებელია აბსტრაქტული კლასებისა და მეთოდების განსასაზღვრად; 2) მეთოდი ნაცვლად ფიგურული ფრჩხილებისა {}, მთავრდება პირდაპირ წერტილმძიმით;


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

  • თუ კლასი არის აღწერილი როგორც abstract, არ არის აუცილებელი რომ იგი შეიცავდეს აბსტრაქტულ მეთოდებს;
  • აბსტრაქტურლი კლასი შეიძლება შეიცავდეს რეალიზებულ(არა აბსტრაქტულ) მეთოდებსა და კლასის ცვლადებს;
  • თუ კლასი შეიცავს თუნდაც ერთ abstract მეთოდს მაშინ თავად კლასიც უნდა იყოს აღწერილი როგორც abstract;
  • abstract მეთოდი ყოველთვის მთავრდება წერტილმძიმით ნაცვლად ფიგურული ფრჩხილებისა;
  • abstract მეთოდს უნდა გააჩნდეს public, protected ან ნაგულისხმევი წვდომის მოდიფიკატორი, private მოდიფიკატორის გამოყენება დაუშვებელი და შეუძლებელია;
  • შეუძლებელია აბსტრაქტული კლასისა და/ან მეთოდის აღწერა როგორც final;
  • კონკრეტული კლასი რომელიც არის მემკვიდრე აბსტრაქტული კლასისა, უნდა იყოს აღწერილი როგორც abstract თუ იგი არ ახდენს რომელიმე აბსტრაქტული მეთოდის რეალიზაციას;
  • აბსტრაქტული კლასის ინსტანციაცია(ობიექტის შექმნა) შეუძლებელია;

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

მაგალითად კლასების ასეთი გამოყენება სავსებით დასაშვებია:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//SomeClass არის აბსტრაქტურლი
abstract class SomeClass {
  abstract void implementMe();
}


//RegularClass არის ჩვეულებრივი არა აბსტრაქტურლი კლასი
//იგი მემკვიდრეა SomeClass აბსტრაქტურლი კლასისა
class RegularClass extends SomeClass {
        //SomeClass აბსტრაქტურლი კლასის აბსტრაქტული implementMe() მეთოდის რეალიზაცია
  void implementMe() {
    //rest of code here
  }
}


//MyAbstractClass არის აბსტრაქტურლი კლასი, რომელიც მემკვიდრეა RegularClass არა აბსტრქტული კლასისა
abstract class MyAbstractClass extends RegularClass {
  //აბსტრაქტული მეთოდი
  abstract void myMethod();
 
}

ასევე სავსებით დასაშვებია შემდეგი სახის კოდის დაწერა:

1
2
3
4
5
6
7
8
9
//ინტერფეისი Movable
interface Movable {
  void move();
}

//MyAbstractClass აბსტრაქტული კლასი
abstract class MyAbstractClass implements Movable {
  //კლასი ცარიელია, მასში არაფერი არ არის რეალიზებული
}

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//ზოგადი GraphicObject კლასი
abstract class GraphicObject {
    //ცვლადები კოორდინატთა ღერძისათვის
    int x, y;
   
    //რეალიზებული არა აბსტრაქტული მეთოდი რომელსაც შეუძლია ფიგურისათვის პოზიციის შეცვლა
    void moveTo(int newX, int newY) {
        //
    }

    //აბსტრაქტული მეთოდი ფიგურის დასახატად
    abstract void draw();
    //აბსტრაქტული მეთოდი ფიგურის ზომის შესაცვლელად
    abstract void resize();
}

//კლასი Circle (წრეწირი) რომელიც არის აბსტრაქტული GraphicObject კლასის მემკვიდრე
class Circle extends GraphicObject {
    //აბსტრაქტული მეთოდის რეალიზაცია
    void draw() {
        //დახატვის ალგორითმი განსხვავდება წრეწირისათვის
    }

    //აბსტრაქტული მეთოდის რეალიზაცია
    void resize() {
        //ზომის შეცვლის კოდი განსხვავდება წრეწირისათვის
    }
}

//კლასი Rectangle (მართკუთხედი) რომელიც არის აბსტრაქტული GraphicObject კლასის მემკვიდრე
class Rectangle extends GraphicObject {
   
    //აბსტრაქტული მეთოდის რეალიზაცია
    void draw() {
        //დახატვის ალგორითმი განსხვავდება მართკუთხედისათვის
    }

    //აბსტრაქტული მეთოდის რეალიზაცია
    void resize() {
        //ზომის შეცვლის კოდი განსხვავდება მართკუთხედისათვის
    }
}

მაგალითი ძალიან მარტივია, იგი შედგება ერთი აბსტრაქტული GraphicObject კლასისაგან, და ორი კონკრეტული რეალიზაციის კლასისაგან Circle და Rectangle. კოდიდან მარტივი მისახვედრია თუ რა უპირატესობას გვაძლევს ამ შემთხვევაში აბსტრაქტული კლასის გამოყენება. გამომდინარე იქედან რომ გეომეტრიულ ფიგურებს მეტნაკლებად მსგავსი ან საერთო მახასიათებლები გააჩნიათ, შესაძლებელია მათი ერთ მშობელ კლასში აღწერა/რეალიზაცია, თუმცა ისეთი მეთოდები როგორიცაა draw და resize შეუძლებელია რომ ყოველი ფიგურისათვის იყოს საერთო. სწორედ ეს მეთოდებია აღწერილი როგორც აბსტრქტული მშობელ GraphicObject კლასში, და მათი რეალიზაცია დამოკიდებულია კონკრეტულ გეომეტრიულ ფიგურაზე. თუმცა მთავარი უპირატესობა ასეთი მიდგომისა არის ის რომ სამუშაო ინტერფეისი ყოველი ფიგურისათვის არის აბსოლუტურად ერთგვაროვანი, და ნებისმიერი ვინც კი იცის ფიგურებთან მუშაობის კლასის მეთოდების შესახებ მარტივად შეძლებს კონკრეტული რეალიზაციის კლასის ობიექტის გამოყენებას ისე რომ მისთვის აბსოლუტურად უმნიშვნელო იქნება: 1) თვითონ კონკრეტული რეალიზაციის კლასის ობიექტის ტიპი; 2) გრაფიკული მეთოდების რეალიზაციის დეტალები;

ტეგები:

One Response to “Java: აბსტრაქტული კლასები”

  1. ანდრო says:

    მშვენიერი არტიკლია!

დატოვე კომენტარი:

ქართული კლავიატურა, ჩართვა/გამორთვა კლავიშით "~"