1. Abstrakt siniflər və metodlar
Bəzən həyatda (və proqramlaşdırmada) demək istəyirsən: “Bilmirəm bu dəqiqə necə edilir, amma dəqiq bilirəm ki, bu olmalıdır!” Məsələn, bütün heyvanlar səs çıxarmağı bacarmalıdır, amma hansı səsi — konkret heyvandan asılıdır. Məhz belə hallarda Java-da abstrakt siniflər və abstrakt metodlar düşünülüb.
Abstrakt sinif — birbaşa yaradıla bilməyən sinifdir (əgər Animal abstraktdırsa, new Animal() yazmaq olmaz), lakin ondan miras almaq mümkündür. Belə sinif həm adi (reallaşdırılmış) metodlar, həm də abstrakt — yəni elan olunmuş, amma reallaşdırılmamış metodlar saxlaya bilər.
Abstrakt metod — gövdəsi olmayan metoddur. O, abstract açar sözü ilə elan olunur və mütləq şəkildə törəmə siniflərdə reallaşdırılmalıdır (yalnız o halda deyil ki, törəmə sinifin özü də abstraktdır).
Həyatdan nümunə
Tutaq ki, zoopark üçün tətbiqimiz var. Bütün heyvanlarda makeSound() metodu olsun istəyirik, amma onların hansı səsi çıxardığını bilmirik. Onda abstrakt sinif yaradırıq:
public abstract class Animal {
public abstract void makeSound(); // Abstrakt metod
}
Və konkret heyvanlar bu metodu özlərinə uyğun reallaşdırırlar:
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Hav-hav!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Miyau!");
}
}
İndi kimsə new Animal() yaratmağa çalışsa, kompilyator dərhal deyəcək: “Bağışla, amma abstrakt heyvanlar təbiətdə olmur!” Bu faydalıdır: siz proqramınızda yalnız konkret davranışa malik konkret heyvanların mövcud olacağına zəmanət verirsiniz.
2. Abstraksiya vasitəsilə polimorfizm
Abstraksiya — obyektlər qrupuna ümumi interfeysin ayrılmasıdır. Abstrakt sinif məhz bu ümumi interfeysi təyin edir: o, bütün törəmələrin hansı metodları mütləq reallaşdırmalı olduğunu deyir.
Polimorfizm və abstraksiya birlikdə işləyir: abstrakt sinif bütün törəmələrdə lazım olan metodların olmasını təmin edir, polimorfizm isə həmin metodları baza tipinə istinad vasitəsilə çağırmağa imkan verir.
Nümunə: zoopark yaradırıq
Gəlin kiçik bir zoopark yığaq. Bizdə abstrakt Animal sinfi və onun bir neçə törəməsi var:
public abstract class Animal {
public abstract void makeSound();
}
public class Cow extends Animal {
@Override
public void makeSound() {
System.out.println("Mööö!");
}
}
public class Duck extends Animal {
@Override
public void makeSound() {
System.out.println("Vak-vak!");
}
}
İndi heyvanlardan ibarət massiv yarada bilərik:
Animal[] zoo = {
new Dog(),
new Cat(),
new Cow(),
new Duck()
};
for (Animal animal : zoo) {
animal.makeSound(); // Hər heyvan üçün “doğru” metod çağırılacaq
}
Massivdəki hər obyekt — konkret heyvandır, amma kod üçün bu sadəcə Animal-dır. Polimorfizm və abstraksiyanın sayəsində hər obyektin makeSound() metoduna malik olduğuna və onun düzgün işləyəcəyinə əmin ola bilərik.
3. Polimorfizm üçün abstrakt siniflərin istifadəsi
Daha praktik bir nümunəyə baxaq. Tutaq ki, şirkətin əməkdaşlarını idarə etmək üçün tətbiq hazırlayırıq. Müxtəlif tip əməkdaşlarımız var: menecerlər, tərtibatçılar, testçilər. Hamısında ümumi work() metodu var, amma onu fərqli şəkildə yerinə yetirirlər.
Abstrakt Employee sinfi
public abstract class Employee {
protected String name;
public Employee(String name) {
this.name = name;
}
public abstract void work();
}
Konkret alt siniflər
public class Manager extends Employee {
public Manager(String name) {
super(name);
}
@Override
public void work() {
System.out.println(name + " komandaya rəhbərlik edir.");
}
}
public class Developer extends Employee {
public Developer(String name) {
super(name);
}
@Override
public void work() {
System.out.println(name + " kod yazır.");
}
}
public class Tester extends Employee {
public Tester(String name) {
super(name);
}
@Override
public void work() {
System.out.println(name + " tətbiqi test edir.");
}
}
Polimorfizmin istifadəsi
İndi əməkdaşlardan ibarət massiv yarada və hər biri üçün work() metodunu çağıra bilərik:
Employee[] employees = {
new Manager("Anna"),
new Developer("Ivan"),
new Tester("Mariya")
};
for (Employee e : employees) {
e.work();
}
Nəticə:
Anna komandaya rəhbərlik edir.
Ivan kod yazır.
Mariya tətbiqi test edir.
Nəzərə alın: dövrdə hansı tip əməkdaş olduğumuzu bilmirik (və bilmək istəmirik!). Sadəcə work() çağırırıq və hər obyekt öz işini görür.
4. Faydalı incəliklər
Metodların reallaşdırılmasına zəmanət
Abstrakt sinif bütün törəmələri lazım olan metodları reallaşdırmağa məcbur edir. Əgər alt sinifdə abstrakt metodu reallaşdırmağı unutsanız, kompilyator dərhal sizi xəbərdar edəcək: “Bunu etməlisən!”
Universal interfeys
Abstrakt tipli massiv və ya siyahı ilə işləyən kod (Employee[], List<Animal>) tamamilə universal ola bilər. Yeni alt siniflər əlavə edə bilərsiniz — əsas kodu dəyişməyə ehtiyac qalmayacaq.
Uyğunsuz obyektlərdən qorunma
Abstrakt sinfi birbaşa yaratmaq mümkün olmadığından, heç kim təsadüfən lazım olan metodları reallaşdırmayan “uyğunsuz” obyekt yarada bilməyəcək.
Nəzəriyyə və sintaksis: abstrakt sinif və metod necə elan olunur
- Abstrakt sinif class sözündən əvvəl abstract açar sözü ilə elan edilir.
- Abstrakt metod abstract açar sözü ilə elan olunur və gövdəsi olmur (yalnız nöqtə-vergül).
- Heç olmasa bir abstrakt metodu olan sinif mütləq abstrakt olmalıdır.
- Abstrakt sinfi miras alan sinif onun bütün abstrakt metodlarını reallaşdırmalıdır, əks halda həmin sinifin özü də abstrakt olmalıdır.
Sxem
public abstract class Animal {
public abstract void makeSound();
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Miyau!");
}
}
5. Abstrakt siniflərlə işləyərkən tipik xətalar
Səhv № 1: abstrakt sinifin obyektini yaratmağa cəhd.
new Animal() kimi kod kompilyasiya olunmayacaq. Abstrakt sinif — hissələri olmayan mebelin yığım təlimatı kimidir: konkret alt sinif ortaya çıxmadan obyekt “yığmaq” mümkün deyil.
Səhv № 2: alt sinifdə abstrakt metodu reallaşdırmağı unutmaq.
Əgər abstrakt metod elan etmisinizsə, amma onu törəmədə reallaşdırmamısınız (və sinfi də abstrakt etməmisinizsə), kompilyator məyus olacaq və xəta göstərəcək.
Səhv № 3: giriş (access) modifikatorlarını unutmaq.
Yenidən müəyyən edilmiş metod baza sinfindəkindən daha sərt giriş modifikatoruna malik ola bilməz. Məsələn, əgər abstrakt metod public idisə, reallaşdırma da public olmalıdır (yoxsa protected və ya private deyil).
Səhv № 4: gövdəsi olan abstrakt metoddan istifadə cəhdi.
abstract metodun gövdəsi ola bilməz, əks halda kompilyator “ya abstraksiya, ya reallaşdırma — qərar ver!” deyəcək.
Səhv № 5: statik metodlar üçün polimorfizmin işləməməsi.
Polimorfizm yalnız qeyri-statik metodlar üçün işləyir. Statik metodlar yenidən təyin olunmur — onlar gizlədilir, buna görə çağırış zamanı davranış dəyişənin tipindən asılı olur, faktiki obyektdən yox.
GO TO FULL VERSION