Panduan Warisan di Jawa

1. Gambaran keseluruhan

Salah satu prinsip utama Pengaturcaraan Berorientasikan Objek - pewarisan - membolehkan kita menggunakan semula kod yang ada atau memperluas jenis yang ada.

Secara sederhana, di Java, kelas dapat mewarisi kelas lain dan pelbagai antara muka, sementara antara muka dapat mewarisi antara muka lain.

Dalam artikel ini, kita akan bermula dengan keperluan untuk mewarisi, beralih ke cara warisan berfungsi dengan kelas dan antara muka.

Kemudian, kita akan membahas bagaimana nama pemboleh ubah / kaedah dan pengubah akses mempengaruhi anggota yang diwarisi.

Dan pada akhirnya, kita akan melihat apa maksudnya mewarisi jenis.

2. Keperluan Warisan

Bayangkan, sebagai pengeluar kereta, anda menawarkan pelbagai model kereta kepada pelanggan anda. Walaupun model kereta yang berbeza mungkin menawarkan ciri yang berbeza seperti tingkap pelindung matahari atau pelindung peluru, semuanya termasuk komponen dan ciri umum, seperti mesin dan roda.

Adalah masuk akal untuk membuat reka bentuk asas dan memperluasnya untuk membuat versi khusus mereka, daripada merancang setiap model kereta secara berasingan, dari awal.

Dengan cara yang serupa, dengan mewarisi, kita dapat membuat kelas dengan ciri dan tingkah laku asas dan membuat versi khusus, dengan membuat kelas, yang mewarisi kelas asas ini. Dengan cara yang sama, antara muka dapat memperluas antara muka yang ada.

Kami akan melihat penggunaan beberapa istilah untuk merujuk kepada jenis yang diwarisi oleh jenis lain, khususnya:

  • jenis asas juga dipanggil jenis super atau induk
  • jenis turunan disebut sebagai jenis lanjutan, sub atau anak

3. Warisan Kelas

3.1. Memperluaskan Kelas

Kelas boleh mewarisi kelas lain dan menentukan ahli tambahan.

Mari mulakan dengan menentukan Kereta kelas asas :

public class Car { int wheels; String model; void start() { // Check essential parts } }

Kelas ArmoredCar boleh mewarisi anggota kereta kelas dengan menggunakan kata kunci memanjangkan dalam perisytiharannya :

public class ArmoredCar extends Car { int bulletProofWindows; void remoteStartCar() { // this vehicle can be started by using a remote control } }

Kita sekarang boleh mengatakan bahawa kelas ArmoredCar adalah subkelas Car, dan yang terakhir adalah kelas super ArmoredCar.

Kelas di Java menyokong warisan tunggal ; yang ArmoredCar kelas tidak boleh melanjutkan pelbagai kelas.

Juga, perhatikan bahawa jika tidak ada kata kunci yang diperluas , kelas secara tidak langsung mewarisi kelas java.lang.Object .

Kelas subkelas mewarisi anggota dilindungi dan awam yang tidak statik dari kelas superclass. Di samping itu, ahli dengan akses lalai dan pakej diwarisi jika kedua-dua kelas berada dalam pakej yang sama.

Sebaliknya, anggota kelas swasta dan statik tidak diwarisi.

3.2. Mengakses Anggota Ibu Bapa dari Kelas Kanak-kanak

Untuk mengakses harta atau kaedah yang diwarisi, kita boleh menggunakannya secara langsung:

public class ArmoredCar extends Car { public String registerModel() { return model; } }

Perhatikan bahawa kami tidak memerlukan rujukan ke superclass untuk mengakses ahlinya.

4. Warisan antara muka

4.1. Melaksanakan Pelbagai Antaramuka

Walaupun kelas hanya dapat mewarisi satu kelas, mereka dapat melaksanakan pelbagai antara muka.

Bayangkan ArmoredCar yang kita tentukan di bahagian sebelumnya diperlukan untuk pengintip super. Oleh itu syarikat pembuatan kereta berfikir untuk menambah fungsi terbang dan terapung:

public interface Floatable { void floatOnWater(); }
public interface Flyable { void fly(); }
public class ArmoredCar extends Car implements Floatable, Flyable{ public void floatOnWater() { System.out.println("I can float!"); } public void fly() { System.out.println("I can fly!"); } }

Dalam contoh di atas, kita dapati penggunaan kata kunci alat untuk mewarisi dari antara muka.

4.2. Masalah Dengan Warisan Berganda

Java membenarkan pelbagai warisan menggunakan antara muka.

Sehingga Java 7, ini bukan masalah. Antaramuka hanya dapat menentukan kaedah abstrak , yakni kaedah tanpa pelaksanaan. Oleh itu, jika kelas melaksanakan pelbagai antara muka dengan tandatangan kaedah yang sama, itu tidak menjadi masalah. Kelas pelaksana akhirnya hanya mempunyai satu kaedah untuk dilaksanakan.

Mari lihat bagaimana persamaan sederhana ini berubah dengan pengenalan kaedah lalai dalam antara muka, dengan Java 8.

Bermula dengan Java 8, antaramuka dapat memilih untuk menentukan implementasi lalai untuk metodenya (antara muka masih dapat menentukan kaedah abstrak ). Ini bermaksud bahawa jika kelas menerapkan beberapa antara muka, yang menentukan kaedah dengan tanda tangan yang sama, kelas anak akan mewarisi pelaksanaan yang berasingan. Ini terdengar rumit dan tidak dibenarkan.

Java tidak membenarkan pewarisan pelbagai pelaksanaan dengan kaedah yang sama, yang ditentukan dalam antara muka yang berasingan.

Inilah contohnya:

public interface Floatable { default void repair() { System.out.println("Repairing Floatable object"); } }
public interface Flyable { default void repair() { System.out.println("Repairing Flyable object"); } }
public class ArmoredCar extends Car implements Floatable, Flyable { // this won't compile }

Sekiranya kita ingin melaksanakan kedua-dua antara muka, kita harus mengganti kaedah pembaikan () .

Sekiranya antara muka pada contoh sebelumnya menentukan pemboleh ubah dengan nama yang sama, katakan jangka masa , kita tidak dapat mengaksesnya tanpa mendahului nama pemboleh ubah dengan nama antara muka:

public interface Floatable { int duration = 10; }
public interface Flyable { int duration = 20; }
public class ArmoredCar extends Car implements Floatable, Flyable { public void aMethod() { System.out.println(duration); // won't compile System.out.println(Floatable.duration); // outputs 10 System.out.println(Flyable.duration); // outputs 20 } }

4.3. Antara Muka Memperluas Antara Muka Lain

Antaramuka dapat memperluaskan pelbagai antara muka. Inilah contohnya:

public interface Floatable { void floatOnWater(); }
interface interface Flyable { void fly(); }
public interface SpaceTraveller extends Floatable, Flyable { void remoteControl(); }

Antaramuka mewarisi antara muka lain dengan menggunakan kata kunci meluas . Kelas menggunakan kata kunci alat untuk mewarisi antara muka.

5. Jenis Warisan

Apabila kelas mewarisi kelas atau antara muka lain, selain mewarisi ahli mereka, kelas itu juga mewarisi jenisnya. Ini juga berlaku untuk antara muka yang mewarisi antara muka lain.

Ini adalah konsep yang sangat kuat, yang membolehkan pemaju memprogramkan ke antara muka (kelas asas atau antara muka) , dan bukannya memprogram untuk pelaksanaannya.

Sebagai contoh, bayangkan keadaan, di mana organisasi menyimpan senarai kereta yang dimiliki oleh pekerjanya. Sudah tentu, semua pekerja mungkin memiliki model kereta yang berbeza. Oleh itu, bagaimana kita boleh merujuk kepada keadaan kereta yang berbeza? Inilah penyelesaiannya:

public class Employee { private String name; private Car car; // standard constructor }

Oleh kerana semua kelas Car yang diturunkan mewarisi jenis Car , contoh kelas yang diturunkan dapat dirujuk dengan menggunakan variabel Car class :

Employee e1 = new Employee("Shreya", new ArmoredCar()); Employee e2 = new Employee("Paul", new SpaceCar()); Employee e3 = new Employee("Pavni", new BMW());

6. Ahli Kelas Tersembunyi

6.1. Ahli Insta Tersembunyi

Apa yang berlaku jika kedua-dua kelas super dan kelas mendefinisikan pemboleh ubah atau kaedah dengan nama yang sama ? Jangan bimbang; kita masih boleh mengakses kedua-duanya. Namun, kita mesti menjelaskan maksud kita kepada Java, dengan awalan pemboleh ubah atau kaedah dengan kata kunci ini atau super .

Kata kunci ini merujuk kepada contoh di mana ia digunakan. Kata kunci super (sepertinya jelas) merujuk kepada contoh kelas induk:

public class ArmoredCar extends Car { private String model; public String getAValue() { return super.model; // returns value of model defined in base class Car // return this.model; // will return value of model defined in ArmoredCar // return model; // will return value of model defined in ArmoredCar } }

Banyak pemaju menggunakan ini dan super katakunci untuk jelas keadaan yang berubah-ubah atau kaedah mereka merujuk kepada. Namun, menggunakannya dengan semua ahli dapat membuat kod kita kelihatan berantakan.

6.2. Ahli Statik Tersembunyi

Apa yang berlaku apabila kelas asas dan subkelas kami menentukan pemboleh ubah dan kaedah statik dengan nama yang sama ? Bolehkah kita mengakses anggota statik dari kelas dasar, di kelas turunan, seperti yang kita lakukan untuk pemboleh ubah contoh?

Mari kita ketahui menggunakan contoh:

public class Car { public static String msg() { return "Car"; } }
public class ArmoredCar extends Car { public static String msg() { return super.msg(); // this won't compile. } }

Tidak, kita tidak boleh. Ahli statik tergolong dalam kelas dan bukan contoh. Oleh itu, kita tidak boleh menggunakan kata kunci super tidak statik di msg () .

Oleh kerana ahli statik tergolong dalam kelas, kami dapat mengubah panggilan sebelumnya seperti berikut:

return Car.msg();

Pertimbangkan contoh berikut, di mana kelas asas dan kelas turunan menentukan kaedah statik msg () dengan tandatangan yang sama:

public class Car { public static String msg() { return "Car"; } }
public class ArmoredCar extends Car { public static String msg() { return "ArmoredCar"; } }

Inilah cara kami memanggil mereka:

Car first = new ArmoredCar(); ArmoredCar second = new ArmoredCar();

Untuk kod sebelumnya, first.msg () akan mengeluarkan "Car " dan second.msg () akan mengeluarkan "ArmoredCar". Mesej statik yang dipanggil bergantung pada jenis pemboleh ubah yang digunakan untuk merujuk kepada contoh ArmoredCar .

7. Kesimpulannya

Dalam artikel ini, kami membahas aspek inti dari bahasa Jawa - pewarisan.

Kami melihat bagaimana Java menyokong warisan tunggal dengan kelas dan pelbagai warisan dengan antara muka dan membincangkan selok-belok bagaimana mekanisme berfungsi dalam bahasa.

Seperti biasa, kod sumber penuh untuk contoh boleh didapati di GitHub.