Warisan adalah konsep penting dalam berorientasi objek. Warisan adalah cara penting lainnya untuk meningkatkan penggunaan kembali kode selain komposisi. Kita melihat dalam komposisi bahwa komposisi adalah antarmuka fungsional suatu objek yang dipanggil berulang kali. Seperti yang akan kita lihat, pewarisan memungkinkan Anda menggunakan kembali definisi kelas yang ada.
Warisan kelas
Saat kami mendefinisikan kelas sebelumnya, kami memulai dari awal dan mendefinisikan setiap anggota kelas secara detail. Misalnya, kelas Manusia berikut:
Copy kode kodenya sebagai berikut:
kelasManusia
{
/**
*aksesor
*/
publik int getHeight()
{
kembalikan ini.tinggi;
}
/**
* mutasi
*/
kekosongan publik tumbuhTinggi(int h)
{
ini.tinggi = ini.tinggi + h;
}
/**
*napas
*/
nafas kosong di depan umum()
{
System.out.println("hu...hu...");
}
tinggi int pribadi;
}
Dari definisi kelas di atas, kita dapat memahami seluruh detail kelas: data anggota kelas, metode kelas, dan antarmuka kelas.
Sekarang kita perlu mendefinisikan kelas baru, seperti kelas Woman, dan berasumsi bahwa Woman sangat mirip dengan kelas Human:
Manusia & Wanita
Kita bisa memulai dari awal dan mendefinisikan sepenuhnya kelas Woman seperti sebelumnya:
Copy kode kodenya sebagai berikut:
kelas Wanita
{
/**
*aksesor
*/
publik int getHeight()
{
kembalikan ini.tinggi;
}
/**
* mutasi
*/
kekosongan publik tumbuhTinggi(int h)
{
ini.tinggi = ini.tinggi + h;
}
/**
*napas
*/
nafas kosong di depan umum()
{
System.out.println("hu...hu...");
}
/**
* metode baru
*/
kelahiran manusia publik()
{
System.out.println("Melahirkan");
kembali (Manusia baru(20));
}
tinggi int pribadi;
}
Seorang programmer akan mengalami banyak kesulitan ketika menulis program di atas. Banyak definisi yang telah ditulis di kelas Human, namun kita harus mengetikkannya kembali. Kelas Woman hanya menambahkan metode giveBirth() baru (metode ini membuat dan mengembalikan objek Manusia baru).
Dengan menggunakan warisan, kita dapat menghindari duplikasi di atas. Biarkan kelas Woman mewarisi dari kelas Human, dan kelas Woman secara otomatis akan memiliki fungsi semua anggota publik di kelas Human.
Kami menggunakan kata kunci extends untuk menunjukkan warisan:
Copy kode kodenya sebagai berikut:
kelas Wanita memperluas Manusia
{
/**
* metode baru
*/
kelahiran manusia publik()
{
System.out.println("Melahirkan");
kembali (Manusia baru(20));
}
}
Dengan cara ini, kami menghemat banyak pengetikan. Melalui pewarisan, kita membuat kelas baru, yang disebut kelas turunan. Kelas yang diwarisi (Manusia) disebut kelas dasar (base class). Kelas turunan menggunakan kelas dasar sebagai dasar definisinya sendiri, dan melengkapi metode giveBirth() yang tidak didefinisikan dalam kelas dasar. Hubungan pewarisan dapat dinyatakan sebagai:
Warisan: Panah menunjuk ke kelas dasar
Anda dapat menggunakan kelas Tes berikut untuk menguji:
Copy kode kodenya sebagai berikut:
Tes kelas publik
{
public static void main(String[] args)
{
Wanita aWanita = Wanita baru();
seorangWanita.growHeight(120);
System.out.println(aWoman.getHeight());
}
}
Lapisan turunan
Melalui pewarisan, kita menciptakan kelas Woman. Keseluruhan proses dapat dibagi menjadi tiga tingkatan: definisi kelas dasar, definisi kelas turunan, dan penggunaan eksternal.
Tingkat definisi kelas dasar adalah untuk mendefinisikan suatu kelas secara normal, seperti definisi kelas Manusia di atas.
Dari sudut pandang pengguna eksternal (seperti objek kelas Woman yang dibuat di kelas Test), kelas turunan memiliki antarmuka eksternal terpadu:
Untuk pengguna eksternal, antarmuka di atas sudah cukup. Dari perspektif antarmuka saja, tidak ada yang istimewa tentang kelas turunan.
Namun, pemrogram harus berhati-hati ketika bekerja pada tingkat definisi kelas turunan:
Pertama, antarmukanya dicampur: metode getHeight() dan GrowHeight() berasal dari kelas dasar, sedangkan metode giveBirth() didefinisikan di dalam kelas turunan.
Ada komplikasi lebih lanjut. Kami sebelumnya dapat dengan bebas mengakses anggota kelas di dalam kelas (menggunakan ini untuk merujuk ke objek). Namun, ketika kita berada dalam lingkup definisi kelas Woman, kita tidak dapat mengakses anggota privat dari kelas dasar Human. Kita ingat arti private: anggota private hanya untuk penggunaan internal kelas. Kelas Woman merupakan kelas baru yang berbeda dengan kelas Manusia, sehingga letaknya berada di luar kelas Manusia. Di kelas turunan, anggota privat dari kelas dasar tidak dapat diakses.
Namun yang menarik adalah metode GrowHeight() dan getHeight() kami masih berfungsi. Hal ini menunjukkan bahwa anggota privat dari kelas dasar ada, hanya saja kita tidak dapat mengaksesnya secara langsung.
Untuk memperjelas konsep ini, kita perlu memahami mekanisme pembangkitan objek kelas turunan. Saat kita membuat objek dari kelas turunan, Java sebenarnya membuat objek kelas dasar (subobjek) terlebih dahulu, dan menambahkan anggota lain yang ditentukan oleh kelas turunan untuk membentuk objek kelas turunan. Apa yang dapat dilihat oleh pengguna eksternal adalah anggota publik dari kelas dasar dan kelas turunan. Seperti yang ditunjukkan di bawah ini:
Objek kelas dasar dan objek kelas turunan
Warna kuning pada gambar merupakan objek kelas dasar. Anggota lapisan dasar dapat mengakses satu sama lain (gunakan ini dalam definisi kelas Manusia untuk merujuk ke objek kelas dasar).
Bagian berwarna biru merupakan isi baru dari objek turunan. Saya menyebut bagian ini sebagai lapisan turunan. Bagian biru dan kuning bersama-sama membentuk objek turunan. Anggota lapisan turunan dapat mengakses satu sama lain (ini dalam definisi Woman). Selain itu, kita juga dapat mengakses anggota publik dari lapisan dasar. Oleh karena itu, kami menggunakan kata kunci super untuk merujuk ke objek kelas dasar, dan menggunakan super.member untuk mewakili anggota dasar (publik).
Ketika kita berada di lapisan turunan (yaitu, ketika mendefinisikan kelas Woman), kita tidak dapat mengakses anggota pribadi basis merah. Saat kita berada di luar, kita tidak dapat mengakses anggota privat lapisan turunan ungu maupun anggota privat lapisan dasar merah.
(Anggota privat pada lapisan turunan memiliki batasan akses, sehingga ditandai dengan garis miring. Anggota privat pada lapisan dasar memiliki batasan akses paling besar, sehingga ditandai dengan garis miring)
Super mirip dengan ini dan juga merupakan parameter implisit. Ketika kita berada pada tingkat definisi kelas yang berbeda, ini akan memiliki arti yang berbeda. Hati-hati dengan kata kunci ini dan super.
(Java tidak memaksakan penggunaan ini dan super. Java dapat secara otomatis mengidentifikasi kepemilikan anggota dalam banyak kasus. Tapi menurut saya ini adalah praktik yang baik.)
terlindung
Kami sebelumnya memperkenalkan dua kata kunci terkait izin akses, pribadi dan publik, yang mengontrol visibilitas eksternal anggota. Sekarang, kami memperkenalkan kata kunci akses baru: dilindungi.
Anggota yang ditandai dilindungi terlihat di kelas ini dan kelas turunannya. Konsep ini mudah dimengerti. Artinya, anggota kelas dasar yang dilindungi dapat diakses oleh lapisan turunan, namun tidak dapat diakses oleh pihak luar, seperti yang ditunjukkan di bawah ini:
penggantian metode
Antarmuka eksternal dari objek kelas turunan pada akhirnya terdiri dari anggota publik dari objek kelas dasar dan anggota publik dari lapisan turunan. Jika anggota publik dari kelas dasar dan anggota publik dari lapisan turunan memiliki nama yang sama, manakah yang akan ditampilkan di antarmuka Java?
Kami telah menyebutkan dalam konstruktor dan kelebihan metode bahwa Java menggunakan nama metode dan daftar parameter untuk menentukan metode yang akan dipanggil. Suatu metode ditentukan oleh nama metode dan daftar parameter. Dalam soal di atas, jika hanya nama metode yang sama tetapi daftar parameternya berbeda, maka kedua metode tersebut akan ditampilkan ke antarmuka secara bersamaan, yang tidak akan menimbulkan masalah bagi kita. Saat melakukan panggilan eksternal, Java akan memutuskan metode mana yang akan digunakan (metode kelebihan beban) berdasarkan parameter yang disediakan.
Bagaimana jika nama metode dan daftar parameter keduanya sama? Saat menurunkan lapisan, kita juga bisa menggunakan super dan ini untuk menentukan metode yang mana. Saat bersifat eksternal, kami hanya menghadirkan antarmuka terpadu, jadi kami tidak dapat menyediakan dua metode sekaligus. Dalam hal ini, Java akan merender metode lapisan turunan, bukan metode lapisan dasar.
Mekanisme ini disebut metode overriding. Penggantian metode dapat dimanfaatkan dengan baik untuk mengubah metode anggota kelas dasar. Misalnya, pada lapisan turunan, yaitu saat mendefinisikan Wanita, Anda dapat memodifikasi metode breath() yang disediakan oleh kelas dasar:
Copy kode kodenya sebagai berikut:
kelas Wanita memperluas Manusia
{/**
* metode baru
*/
kelahiran manusia publik()
{
System.out.println("Melahirkan");
kembali (Manusia baru(20));
}
/**
* timpa Manusia.nafas()
*/
nafas kosong di depan umum()
{
super.nafas();
Sistem.keluar.println("su...");
}
}
Perhatikan bahwa kita berada di lapisan turunan saat ini dan masih dapat memanggil metode breath() dari objek kelas dasar melalui super. Saat kita memanggil kelas Woman secara eksternal, karena penggantian metode, kita tidak bisa lagi memanggil metode objek kelas dasar.
Metode overriding mempertahankan antarmuka objek kelas dasar dan menggunakan implementasi lapisan turunan.
Konstruktor
Setelah memahami konsep objek kelas dasar dan lapisan turunan, metode konstruksi kelas turunan lebih mudah dipahami.
Kita perlu mendefinisikan konstruktor dengan nama yang sama dengan kelas dalam definisi kelas turunan. Dalam konstruktor ini:
1. Karena objek kelas dasar dibuat dan diinisialisasi terlebih dahulu saat membuat objek turunan, konstruktor kelas dasar harus dipanggil terlebih dahulu. Kita dapat menggunakan pernyataan super(daftar argumen) untuk memanggil konstruktor kelas dasar.
2. Setelah objek kelas dasar dibuat, mulailah membangun lapisan turunan (menginisialisasi anggota lapisan turunan). Ini sama dengan metode konstruksi pada umumnya, mengacu pada metode konstruksi dan metode pembebanan ulang
Misalnya, dalam program berikut, kelas Human memiliki konstruktor:
Copy kode kodenya sebagai berikut:
kelasManusia
{
/**
* konstruktor
*/
Manusia publik (int h)
{
ini.tinggi = h;
}
/**
*aksesor
*/
publik int getHeight()
{
kembalikan ini.tinggi;
}
/**
* mutasi
*/
kekosongan publik tumbuhTinggi(int h)
{
ini.tinggi = ini.tinggi + h;
}
/**
*napas
*/
nafas kosong di depan umum()
{
System.out.println("hu...hu...");
}
tinggi int pribadi;
}
Definisi kelas turunan kelas Woman dan metode konstruksinya:
Copy kode kodenya sebagai berikut:
kelas Wanita memperluas Manusia
{
/**
* konstruktor
*/
Wanita publik (int h)
{
super(h); // konstruktor kelas dasar
System.out.println("Halo, Pandora!");
}
/**
* metode baru
*/
kelahiran manusia publik()
{
System.out.println("Melahirkan");
kembali (Manusia baru(20));
}
/**
* timpa Manusia.nafas()
*/
nafas kosong di depan umum()
{
super.nafas();
Sistem.keluar.println("su...");
}
}
Meringkaskan
meluas
penggantian metode
terlindung
super.anggota, super()