Salam! Bu günkü mühazirəni inkapulyasiyaya həsr edəcəyik və dərhal örnəklərlə başlayacağıq :)
Qarşında —
adi bir qazlı içki avtomatı. Sənə bir sualım var: bu necə işləyir? Ətraflı cavab verməyə çalış: stəkan haradan çıxır, içəridə temperatur necə saxlanılır, buz harada saxlanılır, avtomat hansı siropu əlavə edəcəyini necə başa düşür və s. Əksəriyyətinin bu suallara cavabı yoxdur. Yaxşı, ola bilsin ki, hər kəs bu cür avtomatlardan istifadə etmir, indiki dövrdə onlar o qədər də məşhur deyil. Başqa bir nümunə gətirməyə çalışaq. Gün ərzində dəfələrlə istifadə etdiyin bir şey. Oh, bir fikrim var!
Deyə bilərsənmi,
Google axtarış sistemi necə işləyir? Sən yazdığın sözlərə əsasən məlumatı necə axtarır? Niyə bu nəticələr yuxarıda, digərləri isə aşağıda yerləşir? Hər gün google-dan istifadə etsən də, yəqin ki, bunu bilmirsən. Amma bu vacib deyil.
Axı sənə bunu bilmək lazım deyil. Sən axtarış sorğularını daxil edə bilərsən, necə işlədiyini düşünmədən. Avtomat vasitəsilə qazlı içki ala bilərsən, necə qurulduğunu bilmədən. Maşın sürə bilərsən, daxili yanma mühərrikinin işini bilmədən və hətta fizikanı məktəb səviyyəsində belə anlamadan. Bütün bunlar obyekt-yönümlü proqramlaşdırmanın əsas prinsiplərindən biri sayəsində mümkündür —
inkapulyasiya. Bu mövzu ilə əlaqədar məqalələr oxuduğunda, yəqin ki, proqramlaşdırmada iki məşhur anlayışla qarşılaşırsan —
inkapulyasiya və
gizlətmə. Və "inkapulyasiya" dedikdə müəlliflər bəzən birini, bəzən isə digərini nəzərdə tutur. Hər iki termini başa düşməyin üçün izah edəcəyik. "İnkapulyasiya" sözünün başlanğıc mənası proqramlaşdırmada —
məlumatların və məlumatlarla işləmək üsullarının bir qabda (kapsulda) bir araya gətirilməsi deməkdir. Java-da bu qab-kapsul rolunu
klass icra edir. Klass özündə həm
məlumatları (klassın sahələri), həm də bu məlumatlarla işləmək üçün
metodları saxlayır.
Bu sənə açıq-aydın görünə bilər, amma digər proqramlaşdırma konsepsiyalarında hər şey fərqlidir. Məsələn, funksional proqramlaşdırmada məlumatlar əməliyyatlardan kəskin şəkildə ayrılmışdır. OOP-də isə (obyekt-yönümlü proqramlaşdırmada) proqramlar eyni anda həm məlumatlar, həm də onların işlənməsi üçün funksiyalar olan kapsul-klasslardan ibarətdir. İndi
gizlətmə haqqında danışaq. Necə olur ki, müxtəlif mürəkkəb mexanizmlərdən onların necə qurulduğunu və iş prinsipini anlamadan istifadə edə bilirik? Çünki onların yaradıcıları sadə və rahat bir
interfeys təqdim ediblər. Qazlı içki avtomatında interfeys — paneldəki düymələrdir. Bir düyməyə basaraq stəkanın həcmini seçirsən. İkinciyə basaraq sirop seçirsən. Üçüncü düymə isə buzun əlavə edilməsinə cavabdehdir. Bunları etmək kifayətdir. Avtomatın içəridə necə qurulduğu vacib deyil. Əsas odur ki,
qazlı içki almaq üçün istifadəçi üç düyməyə basmalıdır. Eyni şey avtomobilə də aiddir. Onun içində nə baş verdiyi vacib deyil. Əsas odur ki,
sağ pedal basıldığında avtomobil irəli gedir, sol pedal basıldığında isə tormozlanır. Gizlətmənin mahiyyəti bundadır. Proqramın bütün "içərisi" istifadəçidən gizlədilir. Bu məlumatlar onun üçün lazımsızdır. İstifadəçiyə lazım olan şey son nəticədir, daxili proses deyil. Məsələn,
Məlumatların gizlədilməsində bizə kömək edənlər:



Auto
klassına baxaq:
public class Auto {
public void gas() {
/*avtomobilin içərisində mürəkkəb işlər baş verir
nəticə olaraq avtomobil irəli hərəkət edir*/
}
public void brake() {
/*avtomobilin içərisində mürəkkəb işlər baş verir
nəticə olaraq avtomobil tormozlanır*/
}
public static void main(String[] args) {
Auto auto = new Auto();
//İstifadəçiyə necə görünür
//bir pedal basıldı - irəli getdi
auto.gas();
//digər pedal basıldı - tormozlandı
auto.brake();
}
}
Java proqramında realizasiya gizlətməsi bu şəkildə görünür. Real həyatda olduğu kimi: istifadəçiyə interfeys (metodlar) təqdim olunur. Əgər ona avtomobilin proqrama uyğun hərəkəti lazım olsa, lazım olan metodu çağırmaq kifayətdir. Metodların içərisində nə baş verdiyi isə lazımsız məlumatdır, əsas odur ki, hər şey lazım olduğu kimi işləsin. Burada
realizasiya gizlətməsi haqqında danışdıq. Bundan başqa, Java-da
məlumat gizlətməsi də var. Bu haqqında
getterlər və setterlər mövzusunda yazmışdıq, lakin yenidən xatırlamaq faydalı olar. Məsələn, bizim
Cat
klassımız var:
public class Cat {
public String name;
public int age;
public int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Myaau!");
}
}
Ötən mühazirədən bu klassın problemli tərəfi yadında qalıbmı? Yoxdursa, yadına salaq. Problem ondan ibarətdir ki, onun məlumatları (sahələr) hamı üçün açıqdır və başqa bir proqramçı proqram daxilində adısız, çəkisi 0 və yaşı -1000 il olan bir pişik yarada bilər:
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
Bu vəziyyətdə həmkarlarınıza dəqiq nəzarət etmək olar ki, kimsə yanlış vəziyyətdə obyektlər yaratmasın, amma belə "yanlış obyektlərin" yaranma ehtimalını aradan qaldırmaq daha yaxşıdır.

- giriş modifikatorları (private, protected, package default);
- getterlər və setterlər.
- Obyektin düzgün vəziyyətinə nəzarət. Bunun nümunələri yuxarıda idi: setter və private modifikatoru sayəsində proqramımızı 0 çəkili pişiklərdən qorumusuk.
- Interfeys vasitəsilə istifadəçinin rahatlığı. İstifadə üçün yalnız metodları "xaricdə" saxlayırıq. İstifadəçinin lazım olan nəticəni əldə etməsi üçün onları çağırması kifayətdir və metodların iş qaldıqları qərarların detallarını bilməsi lazım deyil.
- Kodda olan dəyişikliklər istifadəçilərə təsir etmir. Bütün dəyişiklikləri metodların daxilində həyata keçiririk. İstifadəçiyə bu təsir etmir: o, maşının qazı üçün auto.gas() yazdığı kimi yazmağa davam edir. Metod gas() içərisində baş verən dəyişikliklər onun üçün anlaşılmaz olur: o, əvvəlki kimi lazım olan nəticəni alır.
GO TO FULL VERSION