CodeGym /Kurslar /JAVA 25 SELF /Giriş modifikatorları

Giriş modifikatorları

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş modifikatorlarının icmalı

Java-da siniflər, sahələr, metodlar və konstruktorlar üçün dörd giriş səviyyəsi var:

Modifikator Harada əlçatandır?
public
Hər yerdə: sinifin daxilində, digər siniflərdə, digər paketlərdə
protected
Sinifin daxilində, alt siniflərdə (varislərdə), eyni paketin digər siniflərində
(package-private)
Yalnız paket daxilində (modifikator açıq şəkildə göstərilməyibsə)
private
Yalnız cari sinfin daxilində

Gəlin hər birini daha ətraflı nəzərdən keçirək — nümunələrlə, azacıq yumorla və gözlənilməz dönüşlərlə.

public — publik giriş

public — bütün dünyaya elan kimidir: “Hər kəsin girişi var!”. Əgər sinif, sahə, metod və ya konstruktor public elan olunubsa, ona istənilən başqa sinifdən, hətta başqa paketdən də müraciət etmək olar.

Nümunə:

public class Cat {
    public String name;
    public void sayMeow() {
        System.out.println("Miyau!");
    }
}

Bu sinifə və onun sahə/metodlarına istənilən yerdən müraciət etmək olar. Əgər sinifinizin hamı üçün əlçatan olmasını istəyirsinizsə, məsələn, kitabxana yazırsınızsa, bu, rahatdır.

Ancaq! Publik sahələr həmişə yaxşı deyil (bax: əvvəlki mühazirə). Adətən yalnız kənardan əlçatan olmalı metodlar public olur, sahələr isə demək olar ki, həmişə private saxlanılır.

private — yalnız sinfin daxilində giriş

private — şifrəli seyf kimidir: sinfin özündən başqa heç kim bu üzvlərə çata bilmir. Hətta varis siniflər (alt siniflər) də private sahə və metodları görmür!

Nümunə:

public class Cat {
    private String secretName;

    public void setSecretName(String name) {
        secretName = name;
    }

    public String getSecretName() {
        return secretName;
    }
}

Burada secretName-ə digər sinifdən birbaşa nə oxumaq, nə də dəyişmək olar. Bunu yalnız Cat sinfinin özü (və ya onun metodları) edə bilər. Bu, inkapsulyasiyanın əsas prinsiplərindən biridir: daxili detalları gizlədirik və onlara yalnız metodlar vasitəsilə çıxış veririk.

protected — qorunan giriş

protected — VIP-keçid kimidir: sinfin özünə, onun varislərinə (başqa paketlərdə olsalar belə) və cari paket daxilindəki bütün siniflərə giriş icazəlidir.

Nümunə:

public class Animal {
    protected int age;

    protected void growOlder() {
        age++;
    }
}

İndi Animal-dan miras alan istənilən sinif age sahəsinə və growOlder() metoduna müraciət edə biləcək.

public class Cat extends Animal {
    public void haveBirthday() {
        growOlder();
        System.out.println("Pişiyin " + age + " yaşı oldu!");
    }
}

Həmçinin protected üzvlərə eyni paket daxilindəki bütün siniflər daxil ola bilər.

(package-private) — paket daxilində giriş

Əgər ümumiyyətlə giriş modifikatoru göstərməsəniz, sinif üzvü package-private (və ya “defolt giriş”) sayılır. Bu, yalnız “özlərimiz” üçündür: yalnız eyni paketdən olan siniflərə icazə var.

Nümunə:

class Dog {
    String name; // package-private
    void bark() { // package-private
        System.out.println("Hav!");
    }
}

Dog sinfi, onun name sahəsi və bark() metodu yalnız eyni paket daxilində əlçatandır. Onlara başqa paketdən müraciət etməyə cəhd etsəniz, kompilyasiya xətası alacaqsınız.

2. Sahələrə və metodlara modifikatorların tətbiqi

Niyə sahələr demək olar ki, həmişə private edilir

Sinfin sahələri onun daxili vəziyyətidir. Onları publik qoysanız, istənilən xarici kod istənilən vaxt dəyişə bilər. Bu, elə bil tanımadığınız uşaqlara mebellərinizi Lego kimi oynamağa icazə verirsiniz: bir gün oyanırsınız, görürsünüz ki, soyuducu vannada tərsinə qoyulub.

Zəif inkapsulyasiya nümunəsi:

public class Person {
    public String name;
    public int age;
}

Yaxşı inkapsulyasiya nümunəsi:

public class Person {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Metodlar (getter və setter-lər) xarici siniflərin sahələri necə dəyişə biləcəyinə nəzarət etməyə imkan verir. Məsələn, mənfi yaşa icazə verməmək olar.

Metodlar nə vaxt public, protected və ya package-private edilir

  • public — metod hamı üçün əlçatan olmalıdırsa. Adətən bu, sinifin əsas funksionallığıdır.
  • protected — metod yalnız varislərə və ya paket daxilində lazımdırsa (məsələn, alt siniflərdə faydalı ola biləcək köməkçi metodlar).
  • package-private — metod yalnız paket daxilində lazımdırsa, amma kənardan əlçatan olmamalıdırsa (məsələn, daxili realizasiya detallarına aid).
  • private — metod yalnız sinfin öz daxilində istifadə olunursa (məsələn, daxili məntiq üçün köməkçi metodlar).

Nümunə:

public class BankAccount {
    private double balance;

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    protected void applyInterest() {
        balance *= 1.05;
    }

    void internalAudit() {
        // package-private: yalnız paket daxilindəki siniflər üçün
    }

    private void logAction(String action) {
        // yalnız sinfin daxili ehtiyacları üçün
    }
}

3. Kod nümunələri: müxtəlif giriş səviyyələri olan sinif

Elə bir sinif yaradaq ki, hər şey olsun: publik, məxfi, qorunan və paket səviyyəli üzvlər. Eyni zamanda onlara digər siniflərdən müraciət etməyə cəhd edək və nəticəyə baxaq.

package zoo;

public class Animal {
    public String publicName = "Hamı üçün əlçatandır";
    protected String protectedName = "Yalnız alt siniflər və paket üçün";
    String packageName = "Yalnız paket üçün";
    private String privateName = "Yalnız Animal üçün";

    public void publicMethod() {
        System.out.println("Publik metod");
    }

    protected void protectedMethod() {
        System.out.println("Qorunan metod");
    }

    void packageMethod() {
        System.out.println("Paket metodu");
    }

    private void privateMethod() {
        System.out.println("Məxfi metod");
    }
}

İndi bu üzvlərə eyni paketdəki başqa sinifdən müraciət etməyə cəhd edək:

package zoo;

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName);   // OK
        System.out.println(animal.packageName);     // OK
        System.out.println(animal.privateName);  // Xəta: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                   // OK
        animal.packageMethod();                     // OK
        animal.privateMethod();                  // Xəta: private
    }
}

Və indi bu üzvlərə başqa paketdən müraciət etməyə cəhd edək:

package other;

import zoo.Animal;

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName); // Xəta: protected
        System.out.println(animal.packageName);   // Xəta: package-private
        System.out.println(animal.privateName);   // Xəta: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                // Xəta: protected
        animal.packageMethod();                  // Xəta: package-private
        animal.privateMethod();                  // Xəta: private
    }
}

Nəticə:

  • public — hər yerdə əlçatandır.
  • protected — paket daxilində və varislərdə əlçatandır (başqa paketlərdə olsa belə, miras vasitəsilə).
  • package-private — yalnız paket daxilində.
  • private — yalnız sinfin daxilində.

4. Ən yaxşı təcrübələr: giriş modifikatorunu necə seçməli

Görünürlük sahəsini minimuma endirin

Sinif sahə və metodlarını nə qədər az kod görsə, bir o qədər yaxşıdır. Yalnız həqiqətən kənar koda lazım olanları açın. Buna minimal səlahiyyət prinsipi (principle of least privilege) deyilir.

  • Sahələr demək olar ki, həmişə private olmalıdır. İstisnalar — yalnız həqiqi konstanta üçlüləri (public static final), amma bunun barəsində növbəti mühazirələrdə ətraflı danışacağıq.
  • Metodları public edin yalnız sinifin xarici interfeysinin bir hissəsidirsə.
  • Köməkçi metodlar (daxili məntiq) — private.
  • Varislər üçün metodlarprotected.
  • Paket üçün daxili servis metodlarıpackage-private.

Bu niyə vacibdir?

  • Reallaşdırma detallarında hər hansı dəyişiklik, əgər detallar açıqdırsa, özgə kodu poza bilər.
  • Sinfi test etmək və dəstəkləmək çətinləşir.
  • Təsadüfi səhvlər (məsələn, sahənin səhv dəyişdirilməsi) buglara səbəb ola bilər.

Bəzən yeni başlayanlar belə düşünür: “Bu nə qədər çətindir ki, qoy hər şey public olsun!” Amma sonra layihə böyüyəndə, kimsə sinfin sahələrini birbaşa dəyişdiyinə görə proqramın yarısını yenidən yazmaq lazım gəlir.

5. Giriş modifikatorları ilə işləyərkən tipik səhvlər

Səhv № 1: Sahələri public və ya defolt olaraq package-private buraxmaq.
Modifikator göstərilməsə, sahə və ya metod paket daxilindəki bütün siniflər üçün əlçatan olacaq. Kimsə sahələrinizi birbaşa dəyişməyə başlasa, bu, gözlənilməz vəziyyətlərə gətirə bilər.

Səhv № 2: Başqa sinifdən private üzvə müraciət etməyə cəhd.
Kompilyator bunu etməyə icazə verməyəcək — xəta alacaqsınız. Amma birdən bunu reflection vasitəsilə “dolaşmağa” qərar versəniz — buglar və gözlənilməz çökmələr dünyasına xoş gəlmisiniz.

Səhv № 3: Həddindən artıq public.
Hər şeyi ard-arda public elan etsəniz, sinif sanki açıq naqillərlə dolu qutuya çevrilir — istənilən kəs səhv naqili dartıb hər şeyi poza bilər.

Səhv № 4: Yalnız varislərə lazım olan metodlar üçün protected istifadə etməmək.
Metod yalnız törəmə siniflərdə genişləndirmə üçün lazımdırsa, onu protected elan edin, public yox.

Səhv № 5: Gizli package-private görünürlük.
Bəzən modifikatoru göstərməyi unudurlar və metod bütün paket üçün əlçatan olur. Əgər onun private olduğunu düşünürdünüzsə, bu, sizi təəccübləndirə bilər.

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