JavaRush /Java Blogu /Random-AZ /Java-da daxili siniflər və ya daxili siniflər

Java-da daxili siniflər və ya daxili siniflər

Qrupda dərc edilmişdir
Salam! Bu gün biz vacib bir mövzuya baxmağa başlayacağıq - Java-da yuvalanmış siniflərin necə işlədiyi. İngilis dilində onlara yuvalanmış siniflər deyilir. Java sizə başqalarının içərisində bəzi siniflər yaratmağa imkan verir:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Məhz bu siniflər iç içə adlanır. Onlar 2 növə bölünür:
  1. Statik olmayan yuvalanmış siniflər - statik olmayan yuvalanmış siniflər. Onlara başqa bir şəkildə daxili siniflər də deyilir.
  2. Statik iç içə siniflər - statik yuvalanmış siniflər.
Öz növbəsində, daxili siniflər iki xüsusi alt növə malikdir. Daxili sinifin yalnız daxili sinif ola biləcəyindən başqa, bu da ola bilər:
  • yerli sinif
  • anonim sinif
Bir az çətin? :) Əla deyil, aydınlıq üçün burada bir diaqram var. Mühazirə zamanı qəfil çaşqınlıq hiss edirsinizsə, ona qayıdın! İç-içə daxili siniflər - 2Bugünkü mühazirəmizdə biz Daxili siniflər - daxili siniflər haqqında danışacağıq (onlar həm də statik olmayan yuvalanmış siniflərdir, statik olmayan yuvalanmış siniflərdir). Onlar ümumi diaqramda xüsusi olaraq vurğulanıb ki, siz itməyəsiniz :) Gəlin açıq sualdan başlayaq: niyə bu siniflər “daxili” adlanır? Cavab olduqca sadədir: çünki onlar başqa siniflər daxilində yaradılmışdır. Budur bir nümunə:
public class Bicycle {

   private String model;
   private int weight;

   public Bicycle(String model, int weight) {
       this.model = model;
       this.weight = weight;
   }

   public void start() {
       System.out.println("Go!");
   }

   public class HandleBar {

       public void right() {
           System.out.println("Steering wheel to the right!");
       }

       public void left() {

           System.out.println("Steering wheel to the left!");
       }
   }

   public class Seat {

       public void up() {

           System.out.println("The seat is up!");
       }

       public void down() {

           System.out.println("The seat is down!");
       }
   }
}
Burada bir sinifimiz var Bicycle- velosiped. Onun 2 sahəsi və 1 metodu var - start(). İç-içə daxili siniflər - 3Onun adi sinifdən fərqi ondadır ki, onun kodu içəridə yazılmış iki sinfə malikdir Bicycle- bunlar siniflərdir HandleBar(sükan çarxı) və Seat(oturacaq). Bunlar tam hüquqlu siniflərdir: gördüyünüz kimi, onların hər birinin öz metodları var. Bu zaman sizdə belə bir sual yarana bilər: niyə biz bir sinfi digərinin içinə qoyduq? Niyə onları daxili edir? Yaxşı, deyək ki, proqramda sükan və oturacaq üçün ayrıca siniflərə ehtiyacımız var. Ancaq onları yerləşdirməyə ehtiyac yoxdur! Siz müntəzəm dərslər edə bilərsiniz. Məsələn, bu kimi:
public class HandleBar {
   public void right() {
       System.out.println("Steering wheel to the right!");
   }

   public void left() {

       System.out.println("Steering wheel left");
   }
}

public class Seat {

   public void up() {

       System.out.println("The seat is up!");
   }

   public void down() {

       System.out.println("The seat is down!");
   }
}
Çox yaxşı sual! Əlbəttə ki, texniki məhdudiyyətimiz yoxdur - biz bunu bu şəkildə edə bilərik. Söhbət daha çox müəyyən proqram baxımından və həmin proqramın mənasında dərslərin düzgün tərtib edilməsindən gedir. Daxili siniflər başqa bir varlıq ilə ayrılmaz şəkildə əlaqəli olan proqramda müəyyən bir obyekti vurğulamaq üçün siniflərdir. Sükan, oturacaq, pedallar velosipedin komponentləridir. Velosipeddən ayrılaraq, onların mənası yoxdur. Bütün bu sinifləri ayrı ictimai siniflər etsəydik, proqramımız, məsələn, aşağıdakı koda malik ola bilər:
public class Main {

   public static void main(String[] args) {
       HandleBar handleBar = new HandleBar();
       handleBar.right();
   }
}
Ummm... Bu kodun mənasını izah etmək belə çətindir. Bizdə qəribə bir velosiped sükanı var (bu, niyə lazımdır? Düzünü desəm, fikrim yoxdur). Və bu sükan sağa dönür... öz-özünə, velosipedsiz... nədənsə. Sükan çarxının mahiyyətini velosipedin mahiyyətindən ayırmaqla proqramımızın məntiqini itirmişik. Daxili sinifdən istifadə edərək kod tamamilə fərqli görünür:
public class Main {

   public static void main(String[] args) {

       Bicycle peugeot = new Bicycle("Peugeot", 120);
       Bicycle.HandleBar handleBar = peugeot.new HandleBar();
       Bicycle.Seat seat = peugeot.new Seat();

       seat.up();
       peugeot.start();
       handleBar.left();
       handleBar.right();
   }
}
Konsol çıxışı:

Сиденье поднято выше!
Поехали!
Руль влево!
Руль вправо!
Birdən baş verənlər məna kəsb etdi! :) Biz velosiped obyekti yaratdıq. Biz onun iki "əsas obyektini" yaratdıq - sükan və oturacaq. Rahatlıq üçün oturacağı yuxarı qaldırdıq - və getdik: yuvarlanırıq və getməli olduğumuz yerə yönəlirik! :) Bizə lazım olan üsullar lazımi obyektlərə çağırılır. Hər şey sadə və rahatdır. Bu nümunədə sükan və oturacaqların vurğulanması inkapsulyasiyanı gücləndirir (biz müvafiq sinif daxilində velosipedin hissələri haqqında məlumatları gizlədirik) və bizə daha ətraflı abstraksiya yaratmağa imkan verir. İndi başqa bir vəziyyətə baxaq. Deyək ki, biz velosiped və ehtiyat hissələri mağazasını modelləşdirən bir proqram yaratmaq istəyirik. İç-içə daxili siniflər - 4Bu vəziyyətdə əvvəlki həllimiz uğursuz olacaq. Ehtiyat hissələri mağazasının hüdudları daxilində, velosipedin hər bir fərdi hissəsi hətta velosipedin mahiyyətindən başqa bir məna daşıyır. Məsələn, “alıcıya pedal satmaq”, “yeni oturacaq almaq” kimi üsullara ehtiyacımız olacaq. Burada daxili siniflərdən istifadə etmək səhv olardı - yeni proqramımız çərçivəsində velosipedin hər bir fərdi hissəsinin öz mənası var: o, velosipedin mahiyyətindən ayrıdır və heç bir şəkildə onunla bağlı deyil. Daxili siniflərdən istifadə etməyiniz və ya bütün obyektləri ayrı-ayrı siniflərə ayırmağınızla maraqlanırsınızsa, buna diqqət yetirməlisiniz. Obyekt yönümlü proqramlaşdırma əladır, çünki real dünya obyektlərini modelləşdirməyi asanlaşdırır. Daxili siniflərdən istifadə edib-etməmək barədə qərar verərkən bələdçi kimi istifadə edə biləcəyiniz budur. Həqiqi mağazada hissələr velosipedlərdən ayrıdır - bu normaldır. Bu o deməkdir ki, proqram tərtib edərkən bu düzgün olacaq. Yaxşı, biz “fəlsəfəni” sıraladıq :) İndi isə daxili siniflərin vacib “texniki” xüsusiyyətləri ilə tanış olaq. Burada mütləq yadda saxlamalı və başa düşməlisiniz:
  1. Daxili sinfin obyekti “xarici” sinfin obyekti olmadan mövcud ola bilməz.

    Bu məntiqlidir: buna görə də biz onu Seatdaxili HandleBarsiniflər etdik ki, sahibsiz sükan çarxları və oturacaqlar proqramımızda orada-burada görünməsin.

    Bu kod tərtib edilməyəcək:

    public static void main(String[] args) {
    
       HandleBar handleBar = new HandleBar();
    }

    Aşağıdakı mühüm xüsusiyyət bundan irəli gəlir:

  2. Daxili sinfin obyekti “xarici” sinfin dəyişənlərinə çıxışa malikdir.

    BicycleMəsələn, sinfimizə bir dəyişən əlavə edək int seatPostDiameter- oturacaq dirəyinin diametri.

    Sonra daxili sinifdə oturacaq parametrini bizə bildirəcək Seatbir üsul yarada bilərik :getSeatParam()

    public class Bicycle {
    
       private String model;
       private int weight;
    
       private int seatPostDiameter;
    
       public Bicycle(String model, int weight, int seatPostDiameter) {
           this.model = model;
           this.weight = weight;
           this.seatPostDiameter = seatPostDiameter;
    
       }
    
       public void start() {
           System.out.println("Go!");
       }
    
       public class Seat {
    
           public void up() {
    
               System.out.println("The seat is up!");
           }
    
           public void down() {
    
               System.out.println("The seat is down!");
           }
    
           public void getSeatParam() {
    
               System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }

    İndi bu məlumatı proqramımızda əldə edə bilərik:

    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
           Bicycle.Seat seat = bicycle.new Seat();
    
           seat.getSeatParam();
       }
    }

    Konsol çıxışı:

    
    Параметр сиденья: диаметр подседельного штыря = 40

    Diqqət edin:yeni dəyişən ən sərt dəyişdirici ilə elan edilir - private. Və hələ də daxili sinifin girişi var!

  3. Объект внутреннего класса нельзя создать в статическом методе «внешнего» класса.

    Это объясняется особенностями устройства внутренних классов. У внутреннего класса могут быть конструкторы с параметрами or только конструктор по умолчанию. Но независимо от этого, когда мы создаем an object внутреннего класса, в него незаметно передается link на an object «внешнего» класса. Ведь наличие такого an object — обязательное condition. Иначе мы не сможем создавать an objectы внутреннего класса.

    Но если метод внешнего класса статический, значит, an object внешнего класса может вообще не существовать! А значит, логика работы внутреннего класса будет нарушена. В такой ситуации компилятор выбросит ошибку:

    public static Seat createSeat() {
    
       //Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
  4. Внутренний класс не может содержать статические переменные и методы.

    Логика здесь та же: статические методы и переменные могут существовать и вызваться даже при отсутствии an object.

    Но без an object «внешнего» класса доступа к внутреннему классу у нас не будет.

    Явное противоречие! Поэтому наличие статических переменных и методов во внутренних классах запрещено.

    Компилятор выбросит ошибку при попытке их создать:

    public class Bicycle {
    
       private int weight;
    
    
       public class Seat {
    
           //inner class cannot have static declarations
           public static void getSeatParam() {
    
               System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
  5. При создании an object внутреннего класса важную роль играет его модификатор доступа.

    Внутренний класс можно обозначить стандартными модификаторами доступа — public, private, protected и package private.

    Почему это важно?

    Это влияет на то, где в нашей программе мы сможем создавать экземпляры внутреннего класса.

    Если наш класс Seat объявлен How public, мы можем создавать его an objectы в любом другом классе. Единственное требование — an object «внешнего» класса тоже обязательно должен существовать.

    Кстати, мы уже это делали вот здесь:

    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle peugeot = new Bicycle("Peugeot", 120);
           Bicycle.HandleBar handleBar = peugeot.new HandleBar();
           Bicycle.Seat seat = peugeot.new Seat();
    
           seat.up();
           peugeot.start();
           handleBar.left();
           handleBar.right();
       }
    }

    Мы легко получor доступ к внутреннему классу HandleBar из класса Main.

    Если же мы объявим внутренний класс How private, доступ к созданию an objectов у нас будет только внутри «внешнего» класса.

    Создать an object Seat снаружи мы уже не сможем:

    private class Seat {
    
       //methods
    }
    
    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
    
           //Bicycle.Seat has a private access in 'Bicycle'
           Bicycle.Seat seat = bicycle.new Seat();
       }
    }

    Наверное, ты уже понял логику :)

  6. Модификаторы доступа для внутренних классов работают так же, How и для обычных переменных.

    Модификатор protected предоставляет доступ к переменной класса в его классах-наследниках и в классах, которые находятся в том же пакете.

    Так же protected работает и для внутренних классов. Объекты protected внутреннего класса можно создавать:

    • внутри «внешнего» класса;
    • в его классах-наследниках;
    • в тех классах, которые находятся в том же пакете.

    Если у внутреннего класса нет модификатора доступа (package private), an objectы внутреннего класса можно создавать

    • внутри «внешнего» класса;
    • в классах, которые находятся в том же пакете.

    С модификаторами ты уже давно знаком, так что тут проблем не будет.

Hələlik bu qədər :) Amma rahat olmayın! Daxili daxili siniflər gələcək dərslərdə araşdırmağa davam edəcəyimiz kifayət qədər geniş mövzudur. İndi siz kursumuzdan daxili dərslər haqqında mühazirə ilə tanış ola bilərsiniz . Və növbəti dəfə statik iç-içə siniflər haqqında danışacağıq.
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION