CodeGym/Java Blog/Acak/Contoh pewarisan kelas bersarang
John Squirrels
Level 41
San Francisco

Contoh pewarisan kelas bersarang

Dipublikasikan di grup Acak
anggota
Hai! Hari ini kita akan melihat mekanisme penting: warisan di kelas bersarang. Pernahkah Anda berpikir tentang apa yang akan Anda lakukan jika Anda perlu membuat kelas bersarang mewarisi beberapa kelas lain. Jika tidak, percayalah: situasi ini bisa membingungkan, karena ada banyak nuansa.
  1. Apakah kita membuat kelas bersarang mewarisi beberapa kelas? Atau apakah kita membuat beberapa kelas mewarisi kelas bersarang?
  2. Apakah kelas anak/orang tua adalah kelas publik biasa, atau juga kelas bersarang?
  3. Terakhir, tipe kelas bersarang apa yang kita gunakan dalam semua situasi ini?
Ada begitu banyak kemungkinan jawaban untuk semua pertanyaan ini, kepala Anda akan berputar :) Seperti yang Anda ketahui, kita dapat memecahkan masalah yang kompleks dengan membaginya menjadi bagian-bagian yang lebih sederhana. Ayo lakukan itu. Mari kita pertimbangkan masing-masing kelompok kelas bersarang secara bergantian dari dua perspektif: siapa yang dapat mewarisi setiap jenis kelas bersarang, dan siapa yang dapat diwarisi. Mari kita mulai dengan kelas bersarang statis.

Kelas bersarang statis

Contoh pewarisan kelas bersarang - 2Aturan pewarisan mereka adalah yang paling sederhana. Di sini Anda dapat melakukan hampir semua hal yang diinginkan hati Anda. Kelas bersarang statis dapat mewarisi:
  • kelas biasa
  • kelas bersarang statis yang dideklarasikan di kelas luar atau leluhurnya
Ingat contoh dari pelajaran kita tentang kelas bersarang statis.
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 kita coba mengubah kode dan membuat Drawingkelas bersarang statis dan turunannya — 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, tidak ada masalah. Kita bahkan dapat mengeluarkan Drawingkelas dan menjadikannya kelas publik biasa, bukan kelas bersarang statis — tidak ada 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 memahami ini. Tapi kelas apa yang bisa mewarisi kelas bersarang statis? Hampir semua! Bersarang/tidak bersarang, statis/non-statis — tidak masalah. Di sini kita membuat Boeing737Drawingkelas dalam mewarisi Drawingkelas bersarang statis:
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 dapat membuat instance 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());

   }

}
Meskipun Boeing737Drawingkelas kita mewarisi kelas statis, itu sendiri bukanlah kelas statis! Akibatnya, itu akan selalu membutuhkan turunan dari kelas luar. Kita dapat menghapus Boeing737Drawingkelas dari Boeing737kelas dan menjadikannya kelas publik yang sederhana. Tidak ada yang berubah. Itu masih bisa mewarisi Drawingkelas bersarang statis.
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 poin penting adalah bahwa dalam hal ini kita perlu membuat maxPassengersCountvariabel statis menjadi publik. Jika tetap privat, maka kelas publik biasa tidak akan memiliki akses ke sana. Kami telah menemukan kelas statis! :) Sekarang mari beralih ke kelas dalam. Mereka datang dalam 3 jenis: kelas dalam sederhana, kelas lokal, dan kelas dalam anonim. Contoh pewarisan kelas bersarang - 3Sekali lagi, mari beralih dari yang sederhana ke yang rumit :)

Kelas batin anonim

Kelas dalam anonim tidak dapat mewarisi kelas lain. Tidak ada kelas lain yang dapat mewarisi kelas anonim. Itu tidak bisa lebih sederhana! :)

Kelas lokal

Kelas lokal (jika Anda lupa) dideklarasikan di dalam blok kode kelas lain. Paling sering, ini terjadi di dalam beberapa metode kelas luar. Logikanya, hanya kelas lokal lain di dalam metode yang sama (atau blok kode) yang dapat mewarisi kelas lokal. Ini contohnya:
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 kode dari pelajaran kita di kelas lokal. Kelas validator nomor kami memiliki PhoneNumberkelas lokal. Jika kita membutuhkannya untuk mewakili dua entitas berbeda, misalnya, nomor ponsel dan nomor telepon rumah, kita hanya dapat melakukannya dengan metode yang sama. Alasannya sederhana: ruang lingkup kelas lokal terbatas pada metode (blok kode) tempat ia dideklarasikan. Akibatnya, kita tidak akan dapat menggunakannya secara eksternal (termasuk untuk pewarisan kelas). Namun, kemungkinan pewarisan di dalam kelas lokal itu sendiri jauh lebih luas! Kelas lokal dapat mewarisi:
  1. Kelas biasa.
  2. Kelas dalam yang dideklarasikan di kelas yang sama dengan kelas lokal atau di salah satu leluhurnya.
  3. Kelas lokal lain dideklarasikan dengan metode yang sama (blok kode).
Poin pertama dan ketiga terlihat jelas, tapi yang kedua agak membingungkan :/ Mari kita lihat dua contoh. Contoh 1 — "Membuat kelas lokal mewarisi kelas dalam yang dideklarasikan di kelas yang sama dengan kelas lokal":
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 menghapus PhoneNumberkelas dari validatePhoneNumber()metode dan menjadikannya sebagai kelas dalam, bukan kelas lokal. Ini tidak menghentikan kami untuk membuat 2 kelas lokal kami mewarisinya. Contoh 2 — "... atau nenek moyang kelas ini." Sekarang ini sudah lebih menarik. Kita bisa bergerak PhoneNumberlebih tinggi lagi dalam rantai warisan. Mari mendeklarasikan AbstractPhoneNumberValidatorkelas abstrak, yang akan menjadi nenek 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 tidak hanya mendeklarasikannya — kami juga memindahkan PhoneNumberinner class ke dalamnya. Namun, dalam turunannya PhoneNumberValidator, kelas lokal yang dideklarasikan dalam metode dapat mewarisi PhoneNumbertanpa 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
   }
}
Karena hubungan pewarisan, kelas lokal di dalam kelas turunan "melihat" kelas dalam di dalam leluhur. Dan akhirnya, mari kita lanjutkan ke grup terakhir :)

Kelas batin

Kelas dalam yang dideklarasikan dalam kelas luar yang sama (atau dalam turunannya) dapat mewarisi kelas dalam lainnya. Mari jelajahi ini menggunakan contoh kita dengan sepeda dari pelajaran kelas dalam.
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 mendeklarasikan Seatkelas dalam di dalam Bicyclekelas. Jenis jok balap khusus, SportSeatmewarisinya. Namun, kita dapat membuat jenis "sepeda balap" terpisah dan meletakkannya di kelas terpisah:
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 merupakan pilihan. Kelas dalam dari keturunan ( SportBicycle.SportSeat) "melihat" kelas dalam dari leluhur dan dapat mewarisinya. Mewarisi kelas dalam memiliki satu fitur yang sangat penting! Dalam dua contoh sebelumnya, SportSeatkelas kita adalah kelas dalam. Tetapi bagaimana jika kita memutuskan untuk membuat SportSeatkelas publik biasa yang secara bersamaan mewarisi Seatkelas dalam?
// 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 kesalahan! Bisakah Anda menebak mengapa? :) Semuanya mudah. Ketika kami berbicara tentang Bicycle.Seatkelas dalam, kami menyebutkan bahwa referensi ke instance kelas luar secara implisit diteruskan ke konstruktor kelas dalam. Ini berarti Anda tidak dapat membuat Seatobjek tanpa membuat Bicycleobjek. Tapi bagaimana dengan penciptaan SportSeat? Tidak seperti Seat, ia tidak memiliki mekanisme bawaan ini untuk secara implisit mengirimkan referensi ke konstruktor ke instance kelas luar. S hingga, tanpa Bicycleobjek, kita tidak dapat membuat SportSeatobjek, seperti dalam kasus Seat. Oleh karena itu, hanya ada satu hal yang tersisa untuk kita lakukan — secara eksplisit meneruskan SportSeatreferensi ke konstruktor ke suatu Bicycleobjek. Inilah 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 konstruktor superclass menggunakan super(); Now, jika kami ingin membuat SportSeatobjek, tidak ada yang akan menghentikan kami melakukan ini:
public class Main {

   public static void main(String[] args) {

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

   }
}
Fiuh! Pelajaran ini agak panjang :) Tapi Anda belajar banyak! Sekarang saatnya menyelesaikan beberapa tugas! :)
Komentar
  • Populer
  • Baru
  • Lama
Anda harus login untuk memberikan komentar
Halaman ini belum memiliki komentar