1. Abstrakt sinif: əsasları təkrarlayaq
Müqayisəyə keçməzdən əvvəl, abstrakt sinifin nə olduğunu yada salaq.
Abstrakt sinif — birbaşa yaradılması mümkün olmayan sinifdir (yazmaq olmaz: new Animal()), lakin həm adi (reallaşdırması olan), həm də abstrakt (reallaşdırması olmayan) metodlar saxlaya bilər. Abstrakt sinif tez-tez digər siniflər üçün əsas kimi istifadə olunur; həmin siniflər onun davranışını miras alır və/və ya bəzi metodları mütləq reallaşdırmalıdır.
Məsələn, tətbiqimizdə müxtəlif nəqliyyat növləri varsa, abstrakt sinif Transport yarada bilərik:
public abstract class Transport {
private String model;
public Transport(String model) {
this.model = model;
}
public String getModel() {
return model;
}
// Abstrakt metod — reallaşdırma yoxdur, yalnız elan
public abstract void move();
// Adi metod — reallaşdırma var
public void printInfo() {
System.out.println("Nəqliyyatın modeli: " + model);
}
}
Abstrakt sinfin xüsusiyyətləri:
- Sahələr (vəziyyət) saxlaya bilər.
- Reallaşdırılmış metodlar saxlaya bilər.
- Abstrakt metodlar saxlaya bilər (varislərdə reallaşdırılması məcburidir).
- Birbaşa obyekt yaratmaq olmaz.
- Ümumi davranış və vəziyyət üçün istifadə olunur.
2. İnterfeys: əsasları təkrarlayaq
İnterfeys — sinfin reallaşdırmalı olduğu metodların toplusudur. İnterfeys vəziyyəti təsvir etmir (adi sahələr ola bilməz, yalnız konstantalar), və metodların reallaşdırmasını ehtiva etmir (Java 8-ə qədər). İnterfeys — saf müqavilədir: «Əgər məni reallaşdırırsansa, bunu edə bilməlisən».
İnterfeys nümunəsi:
public interface Movable {
void move(int x, int y);
}
İnterfeysin xüsusiyyətləri:
- Vəziyyət saxlamır (yalnız public static final konstantalar).
- Java 8-ə qədər — yalnız abstrakt metodlar (Java 8-dən etibarən default və static metodlar əlavə olundu, buna sonra baxacağıq).
- Metodlar susmaya görə həmişə public abstract-dır.
- Sinif bir neçə interfeysi reallaşdıra bilər.
- Sinfin «nə edə bildiyini» təsvir etmək üçün istifadə olunur.
3. Müqayisə cədvəli: abstrakt sinif vs interfeys
Bu iki aləti üz-üzə müqayisə etməyin vaxtıdır! Budur, aydın bir cədvəl:
| Xüsusiyyət | Abstrakt sinif | İnterfeys |
|---|---|---|
| Sintaksis | |
|
| Obyekt yaratmaq olar? | Xeyr | Xeyr |
| Adi metodlar ola bilər? | Bəli | Java 8-ə qədər — yox, Java 8-dən etibarən yalnız default/static |
| Abstrakt metodlar ola bilər? | Bəli | Bəli (Java 8-ə qədər bütün metodlar abstraktdır) |
| Sahələr (vəziyyət) ola bilər? | Bəli (istənilən sahələr) | Yalnız public static final (konstantalar) |
| Konstruktorlar ola bilər? | Bəli | Xeyr |
| Mirasalma | Yalnız bir abstrakt/adi sinif | Bir neçə interfeys reallaşdırmaq olar |
| Metodların modifikatorları | İstənilən (public, protected, private) | Metodlar susmaya görə public abstract-dır. Java 9-dan etibarən interfeys daxilində istifadə üçün private metodlar əlavə etmək olar |
| Mirasalma vasitəsi | |
|
| Adətən nə üçün istifadə olunur | Ümumi reallaşdırma və vəziyyət | İmkanların, rolların təsviri |
| JDK-dan nümunələr | |
|
4. İnterfeysi nə vaxt, abstrakt sinfi nə vaxt istifadə etməli?
İnterfeysdən bu hallarda istifadə edin:
- Sinfin «nə edə bildiyini» təsvir etmək istəyirsinizsə, bunu necə etdiyinə fikir vermədən.
- Sinfin bir neçə müstəqil imkanı reallaşdıra bilməsi lazımdırsa.
- Məsələn: Comparable (müqayisə oluna bilir), Serializable (sərializasiya oluna bilir), Runnable (axında işə salına bilir).
Abstrakt sinifdən bu hallarda istifadə edin:
- Bütün varislərdə olacaq ümumi reallaşdırma və vəziyyəti təyin etmək istəyirsinizsə.
- Bütün varislərdə müəyyən sahələr və ya reallaşdırması olan metodlar olmalıdırsa.
- Mirasalma — sərt şəkildə «birə-bir»dir: sinif yalnız bir sinifdən (adi və ya abstrakt) miras ala bilər.
Həyati bənzətmələr
- İnterfeys — «sürücülük vəsiqəsi» kimidir: əgər səndə varsa, maşın sürə bilərsən, amma hansı maşında və bunu necə etdiyini heç kim diktə etmir.
- Abstrakt sinif — «avtomobilin ümumi sxemi» kimidir: bütün maşınlarda sükan, pedallar, mühərrik var, lakin hər marka detalları özünəməxsus şəkildə həyata keçirir.
5. Java-nın standart kitabxanasından nümunələr
İnterfeys: Comparable
public interface Comparable<T> {
int compareTo(T o);
}
Bu interfeysi reallaşdıran istənilən sinif compareTo metodunu reallaşdırmalıdır. Məsələn, String, Integer, LocalDate və daha birçoğu.
Abstrakt sinif: AbstractList
public abstract class AbstractList<E> implements List<E> {
// List-in bəzi metodlarının susmaya görə reallaşdırılması
// Bəzi metodlar abstrakt saxlanılıb
}
AbstractList artıq kolleksiyaların bəzi davranışlarını (məsələn, əlavə/çıxarma metodlarını) reallaşdırır, lakin bəzi metodları abstrakt saxlayır ki, varislər onları öz tərzlərində reallaşdıra bilsinlər.
6. Kod nümunələri: praktik müqayisə
İnterfeys
İnterfeys və onu reallaşdıran sinif yaradaq.
public interface Printable {
void print();
}
public class Document implements Printable {
@Override
public void print() {
System.out.println("Sənədi çap edirəm...");
}
}
Abstrakt sinif
İndi abstrakt sinif və onun varisi.
public abstract class Machine {
public void turnOn() {
System.out.println("Maşın işə salındı.");
}
public abstract void work();
}
public class Printer extends Machine {
@Override
public void work() {
System.out.println("Printer çap edir...");
}
}
Sinif həm interfeysi, həm də abstrakt sinfi reallaşdırır
public class SmartPrinter extends Machine implements Printable {
@Override
public void work() {
System.out.println("Ağıllı printer işləyir...");
}
@Override
public void print() {
System.out.println("Ağıllı printer çap edir...");
}
}
7. İnterfeyslərin çoxsaylı reallaşdırılması: niyə bu əladır
Java-da sinif yalnız bir sinifdən (abstrakt və ya adi) miras ala bilər, lakin istənilən sayda interfeysi reallaşdıra bilər! Bu, çevik və genişlənə bilən arxitekturalar qurmağa imkan verir.
public interface Scannable {
void scan();
}
public class MultiFunctionPrinter extends Machine implements Printable, Scannable {
@Override
public void work() {
System.out.println("ÇFQ işləyir...");
}
@Override
public void print() {
System.out.println("ÇFQ çap edir...");
}
@Override
public void scan() {
System.out.println("ÇFQ skan edir...");
}
}
Nə vaxt hansını seçmək ?
- Əgər siz ümumi vəziyyəti olan (məsələn, sahələr) baza funksionallığı layihələndirirsinizsə, abstrakt sinifdən istifadə edin.
- Əgər obyektlərə «imkan etiketləri» (məsələn, «çap edə bilir», «müqayisə oluna bilir», «sərializasiya oluna bilir») əlavə etmək istəyirsinizsə — interfeyslərdən istifadə edin.
- Əmin deyilsinizsə — interfeysdən başlayın. Java-da bu yaxşı təcrübə sayılır: interfeyslər daha çox çeviklik və genişlənmə imkanı verir.
8. Tipik səhvlər və gizli məqamlar
Səhv №1: Bir neçə sinifdən miras almağa çalışırsınız — Java buna icazə vermir!
Sinif yalnız bir sinifdən miras ala bilər, amma çoxlu interfeyslər reallaşdıra bilər. Məsələn, class A extends B, C — səhvdir, amma class A extends B implements X, Y, Z — buyurun.
Səhv №2: İnterfeys və sinif sahələrini qarışdırırsınız.
İnterfeys daxilində yalnız konstantalar (public static final) elan etmək olar. Adi vəziyyəti elan etmək olmaz, məsələn, private int count; — kompilyator dərhal sizi dayandıracaq.
Səhv №3: İnterfeysin bütün metodlarını reallaşdırmamısınız.
Sinif interfeysin heç olmasa bir metodunu belə reallaşdırmırsa — o, abstract kimi elan olunmalıdır, əks halda kompilyator səhv verəcək.
Səhv №4: İnterfeysin və ya abstrakt sinifin obyektini yaratmağa çalışırsınız.
Bu iki tip — «yarımfabrikat»dır. Onları yalnız genişləndirmək olar, birbaşa yaratmaq olmaz:
Printable p = new Printable(); // Səhv!
Machine m = new Machine(); // Səhv!
Səhv №5: İnterfeysin konstruktoru ola biləcəyini düşünürsünüz.
İnterfeyslərin konstruktoru ola bilməz, çünki onlar obyektlərin vəziyyətini təsvir etmirlər. Yalnız siniflərdə (adi və abstrakt) konstruktor olur.
GO TO FULL VERSION