CodeGym /Kurslar /JAVA 25 SELF /Modullar vasitəsilə inkapsulyasiya: eksport və import

Modullar vasitəsilə inkapsulyasiya: eksport və import

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

1. Paketlərin eksportu: kodunuzu kim görür?

Java 9-dan əvvəl hər şey sadə idi. Amma o qədər də təhlükəsiz deyildi. Əgər sinif public idisə, JAR-a və ya classpath-ə çıxış olduqda onu istənilən kəs görə bilirdi. Nəticədə daxili siniflər və hətta bütöv paketlər layihənizin xaricində təsadüfən və ya qəsdən istifadə oluna bilərdi. Bəli, nələri isə private və ya package-private ilə gizlətmək olardı, amma sinif publicdirsə — o, hər kəsə əlçatandır.

Modulların gəlişi ilə bu dəyişdi. İndi hətta sinif public elan olunsa belə, o, yerləşdiyi paket module-info.java-da exports vasitəsilə açıq şəkildə eksport edilməyibsə, başqa moduldən istifadə oluna bilməz.

Bu praktikada necə görünür

Tutaq ki, layihə strukturu belədir:

my-app/
  src/
    core/
      com/example/core/
        CoreService.java
        InternalHelper.java
      module-info.java
    app/
      com/example/app/
        Main.java
      module-info.java

core/module-info.java faylında yazırsınız:

module core {
    exports com.example.core;
}

O zaman yalnız com.example.core paketindəki siniflər digər modullara əlçatan olacaq. Digər paketlərdə olan hər şey (məsələn, com.example.core.internal) görünməyəcək — hətta orada public siniflər olsa belə. Bu, modul inkapsulyasiyasıdır.

Mini-demo: «görünür/görünmür»

core daxilində:

// com/example/core/CoreService.java
package com.example.core;

public class CoreService {
    public void doWork() {
        System.out.println("Work done!");
    }
}

app daxilində:

// com/example/app/Main.java
package com.example.app;

import com.example.core.CoreService;

public class Main {
    public static void main(String[] args) {
        CoreService service = new CoreService();
        service.doWork();
    }
}

Əgər core/module-info.java faylından exports com.example.core; sətrini silsəniz, kompilyasiya zamanı bu xətanı alacaqsınız:

error: package com.example.core is not visible

Hətta CoreService — public olsa belə!

2. Asılılıqların importu: requires və sərt izolasiya

JPMS-də başqa moduldan sinifi sadəcə götürüb istifadə etmək olmur. Asılılığı açıq şəkildə requires vasitəsilə elan etmək lazımdır.

Nümunə

app/module-info.java faylında:

module app {
    requires core;
}

İndi app modulu, core modulunun eksport etdiyi hər şeyi istifadə edə bilər.

Əgər requires core; yazmağı unutdunuzsa, kompilyasiya xətası alacaqsınız:

error: package com.example.core is not visible

və ya

error: cannot access CoreService

Vacib məqam

  • requires paketlər yox, modul səviyyəsində işləyir.
  • Yalnız bir paketi “import” edə bilməzsiniz — yalnız bütün eksport olunan modulu.

3. Müqayisə: modullar və public/private

Modullar siniflər və paketlərin “üzərində” yerləşən yeni inkapsulyasiya səviyyəsi əlavə edir.

Səviyyə Nəyi tənzimləyir? Necə işləyir?
private Giriş sinif daxilində Yalnız bir fayl daxilində
package-private (susmaya görə) Paket daxilində giriş Eyni paketdəki bütün siniflər
public Hamı üçün giriş İstənilən yerdə istənilən kod
module Modullar arasında giriş Yalnız eksport olunan paketlər

Açar fikir:

  • Sinif public ola bilər, amma onun paketi eksport olunmayıbsa, o yalnız modul daxilində əlçatan olacaq.
  • exports vasitəsilə paketin eksportu — digər modulların kodunuzu gördüyü bir “pəncərə” kimidir.

Nümunə: gizlədilmiş reallaşdırma

// com/example/core/internal/SecretSauce.java
package com.example.core.internal;

public class SecretSauce {
    public void addMagic() {}
}

Əgər module-info.java-da com.example.core.internal paketini EKSPORT ETMƏSƏNİZ, heç bir xarici modul bu sinifdən istifadə edə bilməz, hətta o public olsa belə!

4. Nümunə: core və app — API və reallaşdırma

Tipik ssenarini nəzərdən keçirək: core modulu API təqdim edir, app modulu — ondan istifadə edir.

Struktur:

core/
  com/example/core/
    CoreAPI.java
  com/example/core/impl/
    CoreImpl.java
  module-info.java

app/
  com/example/app/
    Main.java
  module-info.java

core/module-info.java:

module core {
    exports com.example.core; // Yalnız API!
    // com.example.core.impl-i eksport etmirik
}

app/module-info.java:

module app {
    requires core;
}

com/example/core/CoreAPI.java:

package com.example.core;

public interface CoreAPI {
    void doSomething();
}

com/example/core/impl/CoreImpl.java:

package com.example.core.impl;

import com.example.core.CoreAPI;

public class CoreImpl implements CoreAPI {
    @Override
    public void doSomething() {
        System.out.println("Doing something!");
    }
}

com/example/app/Main.java:

package com.example.app;

import com.example.core.CoreAPI;
// import com.example.core.impl.CoreImpl; // Bu, kompilyasiya xətasına səbəb olacaq!

public class Main {
    public static void main(String[] args) {
        // CoreImpl impl = new CoreImpl(); // Xəta! Paket eksport edilmir.
        // Yalnız API vasitəsilə görünənləri istifadə etmək olar.
    }
}

Nəticə:

  • app modulu yalnız core modulunun eksport etdiklərini görür.
  • Reallaşdırma (impl) gizlədilib, hətta oradakı siniflər public olsa belə.

5. Praktika: export və görünürlük ilə oynayırıq

Addım 1: export-u silirik

core/module-info.java faylında sətri şərhə alın:

// exports com.example.core;

İndi layihəni kompilyasiya etməyə çalışın. app modulunda kompilyasiya xətası gözləyin — o, com.example.core paketindəki sinifləri görməyəcək.

Addım 2: yalnız API-ni eksport edirik

exports com.example.core; sətrini geri qaytarın, amma com.example.core.impl-i eksport etməyin. app modulunda impl paketindən sinif import etməyə çalışın. Yenə kompilyasiya xətası alacaqsınız — hər şey qaydasındadır!

Addım 3: eksport edilməyən paketdə public sinif

Eksport edilməyən paketdə public sinif yaradın. Ondan başqa moduldan istifadə etməyə çalışın — alınmayacaq. Bu, modul inkapsulyasiyasının iş başında olan halıdır.

6. Bu, IDE-də və «sadə dildə» necə görünür

  • Eksport edilməyən paketdən sinif import etməyə cəhd edərkən IDE xəta ilə vurğulayacaq.
  • İpucu paketin modul tərəfindən eksport edilmədiyini izah edəcək.
  • Lazım olan paket üçün exports əlavə edin — xəta yox olacaq.

Sxem: giriş səviyyələri

+---------------------+
|       MODUL         |
|  (module-info.java) |
+---------------------+
       |
       v
+---------------------+
|      PAKETLƏR       |
|  (package, export)  |
+---------------------+
       |
       v
+---------------------+
|      SİNİFLƏR       |
|  (public/private)   |
+---------------------+
       |
       v
+---------------------+
|  METODLAR/SAHƏLƏR   |
|  (public/private)   |
+---------------------+

7. Vacib nüanslar və xüsusiyyətlər

«Yalnız dostlar» üçün eksport: exports ... to

Bəzən paketi yalnız müəyyən modullar üçün eksport etmək lazımdır (məsələn, testlər və ya xüsusi genişlənmələr üçün):

exports com.example.core.internal to my.special.module, my.test.module;

Artıq yalnız göstərilən modullar bu paketi görəcək.

Bir neçə paketi eksport etmək olarmı?

Bəli! Sadəcə yeni exports sətrləri əlavə edin:

exports com.example.core;
exports com.example.core.api;

“Hər şeyi” eksport etmək olarmı?

Xeyr. Java-nın modul sistemində siz həmişə nələri eksport edəcəyinizi açıq göstərirsiniz. Məhz bu, onun gücüdür.

8. Modul inkapsulyasiyası ilə işləyərkən tipik səhvlər

Səhv №1: public sinifin həmişə görünəcəyini düşünmək.
Əgər paket module-info.java vasitəsilə eksport edilməyibsə, sinif digər modullar üçün görünməyəcək, hətta o public olsa belə. Bu, yeni başlayanlar üçün ən çox rast gəlinən “tələ”dir.

Səhv №2: requires elanını unutmaq.
Modulunuz başqa modulun siniflərindən istifadə edir, amma requires yazılmayıbsa, kompilyasiya xətası alacaqsınız. Asılılıqları açıq şəkildə təsvir etməyi unutmayın.

Səhv №3: eyni paketi iki moduldan eksport etməyə cəhd.
JPMS-də hər paket yalnız bir modul tərəfindən eksport edilə bilər. Bu qaydanı pozsanız, kompilyator sizi dayandıracaq.

Səhv №4: strukturun pozulması — module-info.java düzgün yerdə deyil.
module-info.java faylı modulun mənbələrinin kökündə yerləşməlidir, əks halda modul tanınmayacaq.

Səhv №5: modullar arasında dövri asılılıqlar.
Əgər A modulu B-ni tələb edir, B isə A-nı tələb edirsə — xəta alacaqsınız. Asılılıqlar qrafında dövrlərdən qaçın.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Rəqəmsal alətlər emalatxanası və onların gücünün nümayişi 🛠️
Rəqəmsal alətlər emalatxanası və onların gücünün nümayişi 🛠️
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Xidmətin sirlərinin qoruyucusu 🤫
Xidmətin sirlərinin qoruyucusu 🤫
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION