CodeGym/Blog Java/rawak/Contoh pewarisan kelas bersarang
John Squirrels
Tahap
San Francisco

Contoh pewarisan kelas bersarang

Diterbitkan dalam kumpulan
Hai! Hari ini kita akan melihat mekanisme penting: warisan dalam kelas bersarang. Pernahkah anda terfikir tentang perkara yang akan anda lakukan jika anda perlu menjadikan kelas bersarang mewarisi kelas lain. Jika tidak, percayalah: keadaan ini boleh mengelirukan, kerana terdapat banyak nuansa.
  1. Adakah kita membuat kelas bersarang mewarisi beberapa kelas? Atau adakah kita menjadikan sesetengah kelas mewarisi kelas bersarang?
  2. Adakah kelas anak/ibu bapa kelas awam biasa, atau adakah ia juga kelas bersarang?
  3. Akhir sekali, apakah jenis kelas bersarang yang kami gunakan dalam semua situasi ini?
Terdapat begitu banyak jawapan yang mungkin untuk semua soalan ini, kepala anda akan berputar :) Seperti yang anda tahu, kita boleh menyelesaikan masalah yang kompleks dengan membahagikannya kepada bahagian yang lebih mudah. Jom buat macam tu. Mari kita pertimbangkan setiap kumpulan kelas bersarang mengikut giliran dari dua perspektif: siapa yang boleh mewarisi setiap jenis kelas bersarang, dan siapa yang boleh diwarisinya. Mari kita mulakan dengan kelas bersarang statik.

Kelas bersarang statik

Contoh pewarisan kelas bersarang - 2Peraturan pewarisan mereka adalah yang paling mudah. Di sini anda boleh melakukan hampir apa sahaja yang anda inginkan. Kelas bersarang statik boleh mewarisi:
  • kelas biasa
  • kelas bersarang statik yang diisytiharkan dalam kelas luar atau nenek moyangnya
Ingat contoh daripada pelajaran kami tentang kelas bersarang statik.
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Mari cuba tukar kod dan buat Drawingkelas bersarang statik dan keturunannya — Boeing737Drawing.
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }

   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Seperti yang anda lihat, tiada masalah. Kita juga boleh menarik keluar Drawingkelas dan menjadikannya kelas awam biasa dan bukannya kelas bersarang statik — tiada apa yang akan berubah.
public class Drawing {

}

public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Kami faham ini. Tetapi kelas apakah yang boleh mewarisi kelas bersarang statik? Boleh dikatakan mana-mana! Bersarang/tidak bersarang, statik/tidak statik — tidak mengapa. Di sini kita menjadikan Boeing737Drawingkelas dalam mewarisi Drawingkelas bersarang statik:
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }

   public class Boeing737Drawing extends Drawing {

       public int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Anda boleh membuat contoh Boeing737Drawingseperti ini:
public class Main {

   public static void main(String[] args) {

      Boeing737 boeing737 = new Boeing737(1990);
      Boeing737.Boeing737Drawing drawing = boeing737.new Boeing737Drawing();
      System.out.println(drawing.getMaxPassengersCount());

   }

}
Walaupun Boeing737Drawingkelas kami mewarisi kelas statik, ia bukan statik sendiri! Akibatnya, ia akan sentiasa memerlukan contoh kelas luar. Kita boleh mengalih keluar Boeing737Drawingkelas daripada Boeing737kelas dan menjadikannya kelas awam yang mudah. Tiada perubahan. Ia masih boleh mewarisi Drawingkelas bersarang statik.
public class Boeing737 {

   private int manufactureYear;
   public static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }
}

public class Boeing737Drawing extends Boeing737.Drawing {

   public int getMaxPassengersCount() {

       return Boeing737.maxPassengersCount;

}
Satu-satunya perkara penting ialah dalam kes ini kita perlu membuat maxPassengersCountpembolehubah statik awam. Jika ia kekal peribadi, maka kelas awam biasa tidak akan mempunyai akses kepadanya. Kami telah mengetahui kelas statik! :) Sekarang mari kita beralih ke kelas dalaman. Mereka datang dalam 3 jenis: kelas dalaman ringkas, kelas tempatan dan kelas dalaman tanpa nama. Contoh pewarisan kelas bersarang - 3Sekali lagi, mari kita beralih dari mudah kepada kompleks :)

Kelas dalaman tanpa nama

Kelas dalaman tanpa nama tidak boleh mewarisi kelas lain. Tiada kelas lain boleh mewarisi kelas tanpa nama. Ia tidak boleh menjadi lebih mudah! :)

Kelas tempatan

Kelas tempatan (sekiranya anda terlupa) diisytiharkan di dalam blok kod kelas lain. Selalunya, ini berlaku dalam beberapa kaedah kelas luar. Secara logiknya, hanya kelas tempatan lain dalam kaedah yang sama (atau blok kod) boleh mewarisi kelas tempatan. Berikut adalah contoh:
public class PhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       class CellPhoneNumber extends PhoneNumber {

       }

       class LandlinePhoneNumber extends PhoneNumber {


       }

       // ...number validation code
   }
}
Ini adalah kod daripada pelajaran kami tentang kelas tempatan. Kelas pengesah nombor kami mempunyai PhoneNumberkelas tempatan. Jika kami memerlukannya untuk mewakili dua entiti yang berbeza, contohnya, nombor telefon mudah alih dan nombor telefon talian tetap, kami hanya boleh melakukan ini dalam kaedah yang sama. Sebabnya mudah: skop kelas tempatan terhad kepada kaedah (blok kod) di mana ia diisytiharkan. Akibatnya, kami tidak akan dapat menggunakannya secara luaran (termasuk untuk warisan kelas). Walau bagaimanapun, kemungkinan untuk warisan dalam kelas tempatan itu sendiri adalah lebih luas! Kelas tempatan boleh mewarisi:
  1. Kelas biasa.
  2. Kelas dalaman yang diisytiharkan dalam kelas yang sama dengan kelas tempatan atau dalam salah satu nenek moyangnya.
  3. Satu lagi kelas tempatan diisytiharkan dalam kaedah yang sama (blok kod).
Titik pertama dan ketiga kelihatan jelas, tetapi yang kedua agak mengelirukan :/ Mari kita lihat dua contoh. Contoh 1 — "Menjadikan kelas tempatan mewarisi kelas dalaman yang diisytiharkan dalam kelas yang sama dengan kelas tempatan":
public class PhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       // ...number validation code
   }
}
Di sini kami mengalih keluar PhoneNumberkelas daripada validatePhoneNumber()kaedah dan menjadikannya kelas dalaman dan bukannya kelas tempatan. Ini tidak menghalang kami daripada menjadikan 2 kelas tempatan kami mewarisinya. Contoh 2 — "... atau dalam nenek moyang kelas ini." Sekarang ini sudah lebih menarik. Kita boleh bergerak PhoneNumberlebih tinggi lagi dalam rantaian warisan. Mari kita isytiharkan AbstractPhoneNumberValidatorkelas abstrak, yang akan menjadi moyang PhoneNumberValidatorkelas kita:
public abstract class AbstractPhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

}
Seperti yang anda lihat, kami bukan sahaja mengisytiharkannya — kami juga memindahkan PhoneNumberkelas dalaman ke dalamnya. Walau bagaimanapun, dalam keturunannya PhoneNumberValidator, kelas tempatan yang diisytiharkan dalam kaedah boleh mewarisi PhoneNumbertanpa sebarang masalah!
public class PhoneNumberValidator extends AbstractPhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       // ...number validation code
   }
}
Disebabkan hubungan warisan, kelas tempatan dalam kelas keturunan "melihat" kelas dalaman di dalam moyang. Dan akhirnya, mari kita teruskan ke kumpulan terakhir :)

Kelas dalaman

Kelas dalam yang diisytiharkan dalam kelas luar yang sama (atau dalam keturunannya) boleh mewarisi kelas dalam yang lain. Mari kita terokai ini menggunakan contoh kita dengan basikal daripada pelajaran tentang kelas dalaman.
public class Bicycle {

   private String model;
   private int maxWeight;

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

   public void start() {
       System.out.println("Let's go!");
   }

   class Seat {

       public void up() {

           System.out.println("Seat up!");
       }

       public void down() {

           System.out.println("Seat down!");
       }
   }

   class SportSeat extends Seat {

       // ...methods
   }
}
Di sini kami mengisytiharkan Seatkelas dalaman di dalam Bicyclekelas. Jenis kerusi perlumbaan istimewa, SportSeat, mewarisinya. Tetapi, kita boleh mencipta jenis "basikal lumba" yang berasingan dan meletakkannya dalam kelas yang berasingan:
public class SportBicycle extends Bicycle {

   public SportBicycle(String model, int maxWeight) {
       super(model, maxWeight);
   }


   class SportSeat extends Seat {

       public void up() {

           System.out.println("Seat up!");
       }

       public void down() {

           System.out.println("Seat down!");
       }
   }
}
Ini juga satu pilihan. Kelas dalaman keturunan ( SportBicycle.SportSeat) "melihat" kelas dalaman nenek moyang dan boleh mewarisi mereka. Mewarisi kelas dalaman mempunyai satu ciri yang sangat penting! Dalam dua contoh sebelum ini, SportSeatkelas kami ialah kelas dalaman. Tetapi bagaimana jika kita memutuskan untuk membuat SportSeatkelas awam biasa yang secara serentak mewarisi Seatkelas dalaman?
// Error! No enclosing instance of type 'Bicycle' is in scope
class SportSeat extends Bicycle.Seat {

   public SportSeat() {

   }

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
Kami mendapat ralat! Boleh teka kenapa? :) Semuanya mudah. Apabila kita bercakap tentang Bicycle.Seatkelas dalam, kita menyebut bahawa rujukan kepada contoh kelas luar secara tersirat dihantar kepada pembina kelas dalam. Ini bermakna anda tidak boleh mencipta Seatobjek tanpa mencipta Bicycleobjek. Tetapi bagaimana dengan penciptaan sebuah SportSeat? Tidak seperti Seat, ia tidak mempunyai mekanisme terbina dalam ini untuk secara tersirat memberikan rujukan kepada pembina kepada contoh kelas luar. S sehingga, tanpa Bicycleobjek, kita tidak boleh mencipta SportSeatobjek, sama seperti dalam kes Seat. Oleh itu, hanya ada satu perkara yang tinggal untuk kita lakukan - secara eksplisit menyampaikan kepada SportSeatpembina rujukan kepada Bicycleobjek. Begini cara melakukannya:
class SportSeat extends Bicycle.Seat {

   public SportSeat(Bicycle bicycle) {

       bicycle.super();
   }

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
Kami memanggil pembina superclass menggunakan super(); Now, jika kami ingin mencipta SportSeatobjek, tiada apa yang akan menghalang kami daripada melakukan ini:
public class Main {

   public static void main(String[] args) {

       Bicycle bicycle = new Bicycle("Peugeot", 120);
       SportSeat peugeotSportSeat = new SportSeat(bicycle);

   }
}
Fuh! Pelajaran ini agak panjang :) Tetapi anda belajar banyak! Kini tiba masanya untuk menyelesaikan beberapa tugas! :)
Komen
  • Popular
  • Baru
  • Tua
Anda mesti log masuk untuk meninggalkan ulasan
Halaman ini tidak mempunyai sebarang ulasan lagi