JavaRush /Blog Java /Random-MS /Kelas dalaman bersarang atau Kelas Dalaman di Jawa

Kelas dalaman bersarang atau Kelas Dalaman di Jawa

Diterbitkan dalam kumpulan
hello! Hari ini kita akan mula melihat topik penting - cara kelas bersarang berfungsi di Java. Dalam bahasa Inggeris mereka dipanggil kelas bersarang. Java membolehkan anda membuat beberapa kelas di dalam kelas lain:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Kelas-kelas inilah yang dipanggil bersarang. Mereka dibahagikan kepada 2 jenis:
  1. Kelas bersarang bukan statik - kelas bersarang bukan statik. Mereka juga dipanggil kelas dalaman dengan cara lain.
  2. Kelas bersarang statik - kelas bersarang statik.
Sebaliknya, kelas dalaman mempunyai dua subjenis khas. Selain fakta bahawa kelas dalaman boleh menjadi hanya kelas dalaman, ia juga boleh:
  • kelas tempatan
  • kelas tanpa nama
Susah sikit? :) Tak apa, ini diagram untuk kejelasan. Kembali kepadanya semasa kuliah jika anda tiba-tiba berasa keliru! Kelas dalaman bersarang - 2Dalam kuliah hari ini kita akan bercakap tentang kelas Dalam - kelas dalaman (ia juga kelas bersarang bukan statik, kelas bersarang bukan statik). Mereka diserlahkan khas dalam rajah umum supaya anda tidak tersesat :) Mari kita mulakan dengan soalan yang jelas: mengapa kelas ini dipanggil "dalaman"? Jawapannya agak mudah: kerana ia dicipta di dalam kelas lain. Berikut ialah contoh:
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!");
       }
   }
}
Di sini kita ada kelas Bicycle- basikal. Ia mempunyai 2 medan dan 1 kaedah - start(). Kelas dalaman bersarang - 3Perbezaannya daripada kelas biasa ialah ia mempunyai dua kelas, kod yang ditulis di dalamnya Bicycle- ini adalah kelas HandleBar(roda stereng) dan Seat(tempat duduk). Ini adalah kelas lengkap: seperti yang anda lihat, setiap daripada mereka mempunyai kaedah sendiri. Pada ketika ini, anda mungkin mempunyai soalan: mengapa kami meletakkan satu kelas di dalam kelas lain? Mengapa menjadikan mereka dalaman? Baiklah, katakan kita memerlukan kelas berasingan untuk stereng dan tempat duduk dalam program. Tetapi anda tidak perlu menyarangkannya! Anda boleh membuat kelas biasa. Sebagai contoh, seperti ini:
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!");
   }
}
Soalan yang sangat bagus! Sudah tentu, kami tidak mempunyai had teknikal - kami boleh melakukannya dengan cara ini. Ia lebih kepada mereka bentuk kelas dengan betul dari sudut pandangan program tertentu dan dalam maksud program itu. Kelas dalaman ialah kelas untuk menyerlahkan entiti tertentu dalam atur cara yang berkait rapat dengan entiti lain. Stereng, tempat duduk, pedal adalah komponen basikal. Dipisahkan dari basikal, mereka tidak masuk akal. Jika kami membuat semua kelas ini memisahkan kelas awam, program kami mungkin mempunyai, sebagai contoh, kod berikut:
public class Main {

   public static void main(String[] args) {
       HandleBar handleBar = new HandleBar();
       handleBar.right();
   }
}
Ummm... Maksud kod ni pun susah nak terangkan. Kami mempunyai beberapa hendal basikal yang pelik (mengapa ia diperlukan? Tidak ada idea, sejujurnya). Dan stereng ini berpusing ke kanan... dengan sendirinya, tanpa basikal... atas sebab tertentu. Dengan memisahkan intipati stereng daripada intipati basikal, kami telah kehilangan logik program kami. Menggunakan kelas dalaman, kod itu kelihatan berbeza sama sekali:
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();
   }
}
Output konsol:

Сиденье поднято выше!
Поехали!
Руль влево!
Руль вправо!
Apa yang berlaku tiba-tiba masuk akal! :) Kami telah mencipta objek basikal. Kami mencipta dua daripada "subobjek" - stereng dan tempat duduk. Kami menaikkan kerusi lebih tinggi untuk kemudahan - dan kami pergi: kami bergolek dan memandu ke mana kami perlu pergi! :) Kaedah yang kita perlukan dipanggil pada objek yang diperlukan. Semuanya mudah dan selesa. Dalam contoh ini, menyerlahkan hendal dan tempat duduk meningkatkan enkapsulasi (kami menyembunyikan data tentang bahagian basikal dalam kelas yang sepadan), dan membolehkan kami membuat abstraksi yang lebih terperinci. Sekarang mari kita lihat situasi lain. Katakan kita ingin mencipta program yang memodelkan kedai basikal dan alat ganti. Kelas dalaman bersarang - 4Dalam keadaan ini, penyelesaian kami sebelum ini akan gagal. Dalam lingkungan kedai alat ganti, setiap bahagian individu basikal mempunyai makna walaupun selain daripada intipati basikal. Sebagai contoh, kami memerlukan kaedah seperti "menjual pedal kepada pembeli", "beli tempat duduk baharu", dsb. Ia akan menjadi satu kesilapan untuk menggunakan kelas dalaman di sini - setiap bahagian individu basikal dalam program baharu kami mempunyai makna tersendiri: ia berasingan daripada intipati basikal, dan sama sekali tidak terikat dengannya. Inilah yang perlu anda perhatikan jika anda tertanya-tanya sama ada anda perlu menggunakan kelas dalaman, atau memisahkan semua entiti ke dalam kelas berasingan. Pengaturcaraan berorientasikan objek bagus kerana ia memudahkan untuk memodelkan entiti dunia sebenar. Inilah yang boleh anda gunakan sebagai panduan semasa membuat keputusan sama ada untuk menggunakan kelas dalaman. Di kedai sebenar, bahagian berasingan daripada basikal - ini adalah perkara biasa. Ini bermakna bahawa ini akan betul apabila mereka bentuk program. Okay, kami telah menyelesaikan "falsafah" :) Sekarang mari kita berkenalan dengan ciri "teknikal" penting kelas dalaman. Inilah perkara yang anda perlu ingat dan fahami:
  1. Objek kelas dalam tidak boleh wujud tanpa objek kelas "luar".

    Ini adalah logik: itulah sebabnya kami menjadikannya kelas Seatdalaman HandleBar, supaya stereng dan tempat duduk tanpa pemilik tidak akan muncul di sana sini dalam program kami.

    Kod ini tidak akan disusun:

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

    Ciri penting berikut berikut dari ini:

  2. Objek kelas dalam mempunyai akses kepada pembolehubah kelas "luar".

    Sebagai contoh, mari tambah Bicyclepembolehubah pada kelas kita int seatPostDiameter- diameter tiang tempat duduk.

    Kemudian dalam kelas dalaman Seatkita boleh membuat kaedah getSeatParam()yang akan memberitahu kita parameter tempat duduk:

    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);
           }
       }
    }

    Dan kini kami boleh mendapatkan maklumat ini dalam program kami:

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

    Output konsol:

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

    Beri perhatian:pembolehubah baru diisytiharkan dengan pengubahsuai yang paling ketat - private. Dan kelas dalaman masih mempunyai akses!

  3. Objek kelas dalam tidak boleh dibuat dalam kaedah statik kelas "luar".

    Ini dijelaskan oleh ciri reka bentuk kelas dalaman. Kelas dalaman boleh mempunyai pembina dengan parameter atau hanya pembina lalai. Tetapi tanpa mengira ini, apabila kita mencipta objek kelas dalam, rujukan kepada objek kelas "luar" dialihkan ke dalamnya secara senyap-senyap. Lagipun, kehadiran objek sedemikian adalah prasyarat. Jika tidak, kita tidak akan dapat mencipta objek kelas dalam.

    Tetapi jika kaedah kelas luar adalah statik, maka objek kelas luar mungkin tidak wujud sama sekali! Ini bermakna bahawa logik kelas dalaman akan rosak. Dalam keadaan sedemikian, pengkompil akan membuang ralat:

    public static Seat createSeat() {
    
       //Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
  4. Kelas dalaman tidak boleh mengandungi pembolehubah dan kaedah statik.

    Logik di sini adalah sama: kaedah statik dan pembolehubah boleh wujud dan dipanggil walaupun tiada objek.

    Tetapi tanpa objek kelas "luar", kami tidak akan mempunyai akses kepada kelas dalam.

    Percanggahan yang jelas! Oleh itu, kehadiran pembolehubah statik dan kaedah dalam kelas dalaman adalah dilarang.

    Pengkompil akan membuang ralat apabila cuba menciptanya:

    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. Apabila mencipta objek kelas dalam, pengubah suai aksesnya memainkan peranan penting.

    Kelas dalam boleh dilambangkan dengan pengubah akses standard - public, private, protecteddan package private.

    Mengapa ia penting?

    Ini memberi kesan di mana dalam program kami, kami boleh membuat instantiate kelas dalaman.

    Jika kelas kami Seatdiisytiharkan sebagai public, kami boleh mencipta objeknya dalam mana-mana kelas lain. Satu-satunya keperluan ialah objek kelas "luaran" juga mesti wujud.

    Dengan cara ini, kami telah melakukan ini di sini:

    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();
       }
    }

    Kami dengan mudah mengakses kelas dalaman HandleBardaripada Main.

    Jika kami mengisytiharkan kelas dalam sebagai private, kami hanya akan mempunyai akses untuk mencipta objek dalam kelas "luar".

    SeatKami tidak lagi dapat mencipta objek dari luar:

    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();
       }
    }

    Anda mungkin sudah faham logiknya :)

  6. Pengubah suai akses untuk kelas dalaman berfungsi sama seperti untuk pembolehubah biasa.

    Pengubah suai protectedmenyediakan akses kepada pembolehubah kelas dalam kelas turunannya dan dalam kelas yang berada dalam pakej yang sama.

    Perkara yang sama protectedberfungsi untuk kelas dalaman. Objek protectedkelas dalaman boleh dibuat:

    • di dalam kelas "luar";
    • dalam kelas keturunannya;
    • dalam kelas yang berada dalam pakej yang sama.

    Jika kelas dalam tidak mempunyai pengubah akses ( package private), objek kelas dalam boleh dibuat

    • di dalam kelas "luar";
    • dalam kelas yang berada dalam pakej yang sama.

    Anda sudah lama mengenali pengubah suai, jadi tidak akan ada sebarang masalah di sini.

Itu sahaja buat masa ini :) Tetapi jangan berehat! Kelas bersarang dalaman ialah topik yang agak luas yang akan kami terus terokai dalam pelajaran akan datang. Kini anda boleh membetulkan kuliah mengenai kelas dalaman daripada kursus kami. Dan lain kali kita akan bercakap tentang kelas bersarang statik.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION