CodeGym /Kurslar /C# SELF /İnkapulyasiya və giriş modifikatorları

İnkapulyasiya və giriş modifikatorları

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Təsəvvür elə ki, sən müasir bir maşın layihələndirirsən. İçəridə — yüzlərlə mürəkkəb detal, həssas elektronika, incə sazlamalar var. Aydındır ki, heç kim sadəcə belə mühərrikin idarəetmə blokuna çatıb hansısa vintləri fırlatmamalıdır. Əgər hər kəs ora-bura müdaxilə etsə, maşın gözlənilməz davranmağa başlaya bilər və sənə texniki baxış keçirib, kim nəyi sındırıb tapmaq lazım olacaq.

Proqramlaşdırmada da eyni şeydir. Sinif yaradanda istəyirsən ki, onun içini yad əllərdən qoruya biləsən — heç kim təsadüfən vacib məlumatları pozmasın və ya metodların işinə qarışmasın, hansılar ki, xarici dünya üçün nəzərdə tutulmayıb. Bax, inkapsulyasiya — obyekt yönümlü proqramlaşdırmanın üç əsas prinsipindən biridir — məhz budur.

İnkapulyasiya sənə imkan verir ki, reallaşdırma detallarını gizlədəsən və dəqiq müəyyən edəsən: nə "çöldən" əlçatandır, nə isə içəridə qalmalıdır. Elə bil ki, istifadəçiyə torpido açırsan, amma kapotu möhkəm bağlayırsan. Sinif özü qərar verir ki, hansı məlumatları xarici koda göstərsin, hansını isə gizli saxlasın. Bunun sayəsində kod daha etibarlı, məntiqli və baxımlı olur.

Daha dəqiq desək, inkapsulyasiya — bu, məlumatları (sahələri) və onlarla bağlı davranışı (metodları) bir strukturda birləşdirmək və obyektin daxili komponentlərinə birbaşa çıxışı məhdudlaşdırmaq üsuludur.

2. Giriş modifikatorları: öz ərazimizi qoruyuruq

C#-da (və digər OOP dillərində) inkapsulyasiya giriş modifikatorları ilə həyata keçirilir. Bunlar elə "etiketlərdir" ki, müəyyən edir: sinifin hansı üzvləri (sahələr, metodlar, xüsusiyyətlər və s.) çöldən əlçatandır, hansılar isə yalnız içəridən.

Biz artıq onlarla rastlaşmışıq, amma bir daha xatırladaq və modifikatorların siyahısını bir az genişləndirək:

Modifikator Əlçatandır...
public
Hamıya! Layihədəki istənilən kod (və əgər layihə kitabxanadırsa, onun hüdudlarından kənarda da)
private
Yalnız bu sinifin içindən
protected
Bu sinifdən və bütün onun törəmələrindən
internal
Yalnız cari assembly (layihə) daxilində
protected internal
Ya cari assembly-dən, ya da törəmədən
private protected
Yalnız cari assembly daxilində törəmədən

Bu dərsdə ən çox istifadə olunanlara fokuslanacağıq: public, private və qısa olaraq protected-ə toxunacağıq ki, beynimizi yükləməyək.

Daxili və xarici hissəni ayırırıq

Gəlin Dog sinifini yazaq:


public class Dog
{
    public string Name;
    public int Age;

    public void Bark()
    {
        Console.WriteLine($"{Name} deyir: Hav!");
    }
}

Burada bütün sahələr və metodlar public modifikatoru ilə elan olunub. Bu o deməkdir ki, istənilən adam itin adını və ya yaşını dəyişə bilər:

Dog rex = new Dog("Rex", 5);
rex.Name = "Sarik"; // Gözlənilməz şəxsiyyət dəyişikliyi!
rex.Age = -999;     // Yaşla ciddi problemlər

Halbuki NameAge sahələri — ən vacib məlumatlardır, hansıları ki, istənilən adama vermək istəmirsən.

Belə etmək olmaz

Bütün sahələri public qoyanda, sinifin iş məntiqini poza bilərik: istənilən xarici müdaxilə obyekti qeyri-düzgün edə bilər. Məsələn, itə mənfi yaş vermək və ya adını "%$#!??" kimi etmək olar.

3. Sahələri gizlədirik: private istifadə edirik

Adətən sinifin sahələri qapalı (private modifikatoru ilə) edilir. Bu o deməkdir ki, onların dəyərini yalnız sinifin içindən dəyişmək olar, çöldən isə heç cür.


public class Dog
{
    private string name;
    private int age;

    public void Bark()
    {
        Console.WriteLine($"{name} deyir: Hav!");
    }
}

İndi sahələrə çöldən birbaşa müraciət cəhdi:

Dog rex = new Dog("Rex", 5);
rex.name = "Sarik";  // Kompilyasiya xətası

Kompilyator dərhal deyəcək: "Giriş yoxdur!".

Niyə bu qədər sərt? Bəs elastiklik hanı?

Bütün "elastiklik" xüsusi metodlar və ya xüsusiyyətlər (onlar haqqında növbəti dərsdə daha ətraflı danışacağıq) vasitəsilə təmin olunur, hansılar ki, girişə nəzarət etməyə və məlumatları yalnız müəyyən qaydalara əsasən dəyişməyə imkan verir.

4. İnkapulyasiya praktikada: nəzarət nümunəsi

Tutaq ki, istəyirik ki, itə mənfi yaş vermək mümkün olmasın:


public class Dog
{
    private string name;
    private int age;

    public Dog(string name, int age)
    {
        this.name = name;
        if (age >= 0)
            this.age = age;
        else
            this.age = 0; // "Qəribə" yaş qoymağa imkan vermirik
    }

    public void Bark()
    {
        Console.WriteLine($"{name} deyir: Hav!");
    }

    // Yaşı təhlükəsiz dəyişmək üçün metod
    public void SetAge(int newAge)
    {
        if (newAge >= 0)
            age = newAge;
        // Burada else əlavə etmək olar: dəyərin düzgün olmaması barədə mesaj
    }
}

İndi çöldən heç kim sahələri birbaşa poza bilməz. Yaşı dəyişmək üçün xüsusi metod var, hansı ki, lazımi yoxlamanı aparır.

5. Sahələr və giriş metodları (getter/setter-lər)

Belə üsul — sahələri private edib, onlarla işləmək üçün metodlar vermək — məlumatların inkapsulyasiyası (data encapsulation) adlanır. Sahənin dəyərini oxumaq üçün adətən getter metodları, yazmaq üçün isə setter metodları yaradılır.


public class Dog
{
    private string name;

    public Dog(string name)
    {
        this.name = name;
    }

    public string GetName()
    {
        return name;
    }

    public void SetName(string newName)
    {
        // Burada adın düzgünlüyünü yoxlamaq olar
        name = newName;
    }
}

Amma! C#-da properties (xüsusiyyətlər) çıxdıqdan sonra belə metodlardan daha az istifadə olunur — properties kodu daha təmiz və rahat edir (onlar haqqında — növbəti dərsdə).

6. Metodlar və siniflər üçün giriş modifikatorları

Sahələr — hələ hamısı deyil! Giriş modifikatorları metodlar (sinifin üzv funksiyaları) və hətta siniflərin özləri üçün də istifadə olunur.

Yalnız sinifin içində istifadə olunan metodlar (məsələn, daxili məntiq üçün köməkçi funksiyalar) adətən private edilir.

Publik metodlar — bu, sinifin interfeysidir (açar söz interface ilə qarışdırma), yəni istifadəçinin sinifdən istifadə edə biləcəyi hissədir.

7. İnkapulyasiya ilə işləyərkən tipik səhvlər

Səhv №1: hər şeyi public elan etmək.
Elə gəlir ki, nə qədər çox əlçatan olsa, istifadə etmək bir o qədər asandır. Əslində isə — bu, sinifin daxili hissələrinə çıxışı açır, hansılar ki, çöldən dəyişməməlidir. Belə kod xüsusilə böyük layihələrdə zəif və gözlənilməz olur.

Səhv №2: giriş modifikatorunu dəyişmək xarici kodu pozur.
Refaktoring zamanı təsadüfən metodun və ya sahənin giriş modifikatorunu dəyişə bilərsən və onda onlarla işləyən bütün başqa kodlar birdən kompilyasiya olunmur və ya düzgün işləmir. Xüsusilə publik API-lərdə bu kritikdir.

Səhv №3: lokal dəyişənlərlə sinif sahələrini qarışdırmaq.
Bəzən proqramçılar unudurlar ki, metodun içində elan olunan dəyişən yalnız həmin metodda yaşayır. Sinifin sahələri isə bütün metodlarında əlçatandır. Bu, xüsusilə dəyişən adları üst-üstə düşəndə, aydın olmayan səhvlərə gətirib çıxarır.

Səhv №4: privateprotected-dən istifadə etməmək.
Bir çoxları məhdud girişdən qorxur, fikirləşir ki, sonra lazım olan elementə çata bilməyəcəklər. Amma inkapsulyasiya məhz budur — artıq olanı gizlətmək, çölə isə yalnız həqiqətən lazım olanı çıxarmaq.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION