"Saya akan memberitahu anda tentang « pengubah suai akses ». Saya pernah memberitahu tentangnya sebelum ini, tetapi pengulangan adalah tonggak pembelajaran."
Anda boleh mengawal akses (keterlihatan) yang ada pada kelas lain kepada kaedah dan pembolehubah kelas anda. Pengubah suai akses menjawab soalan «Siapa yang boleh mengakses kaedah/pembolehubah ini?». Anda boleh menentukan hanya satu pengubah suai untuk setiap kaedah atau pembolehubah.
1) pengubah suai « awam ».
Pembolehubah, kaedah atau kelas yang ditandakan dengan pengubah suai awam boleh diakses dari mana-mana sahaja dalam program. Ini adalah tahap keterbukaan tertinggi: tiada sekatan.
2) pengubah suai « persendirian ».
Pembolehubah, kaedah atau kelas yang ditandakan dengan pengubah suai persendirian hanya boleh diakses dalam kelas di mana ia diisytiharkan. Kaedah atau pembolehubah yang ditanda disembunyikan daripada semua kelas lain. Ini ialah tahap privasi tertinggi: hanya boleh diakses oleh kelas anda. Kaedah sedemikian tidak diwarisi dan tidak boleh ditimpa. Selain itu, mereka tidak boleh diakses dalam kelas keturunan.
3) « Pengubah suai lalai».
Jika pembolehubah atau kaedah tidak ditandakan dengan mana-mana pengubah, maka ia dianggap ditandakan dengan pengubah "lalai". Pembolehubah dan kaedah dengan pengubah suai ini boleh dilihat oleh semua kelas dalam pakej di mana ia diisytiharkan, dan hanya kepada kelas tersebut. Pengubah suai ini juga dipanggil akses " pakej " atau " pakej peribadi ", membayangkan fakta bahawa akses kepada pembolehubah dan kaedah terbuka kepada keseluruhan pakej yang mengandungi kelas.
4) " dilindungi " pengubah suai.
Tahap akses ini lebih luas sedikit daripada pakej . Pembolehubah, kaedah atau kelas yang ditandakan dengan pengubah suai yang dilindungi boleh diakses daripada pakejnya (seperti "pakej") dan daripada semua kelas yang diwarisi.
Jadual ini menerangkan semuanya:
Jenis keterlihatan | Kata kunci | Akses | |||
---|---|---|---|---|---|
Kelas awak | Pakej anda | Keturunan | Semua kelas | ||
Persendirian | persendirian | ya | Tidak | Tidak | Tidak |
Pakej | (tiada pengubah suai) | ya | ya | Tidak | Tidak |
Dilindungi | dilindungi | ya | ya | ya | Tidak |
Awam | awam | ya | ya | ya | ya |
Terdapat cara untuk mengingati jadual ini dengan mudah. Bayangkan anda sedang menulis surat wasiat. Anda membahagikan semua perkara anda kepada empat kategori. Siapa yang boleh menggunakan barang anda?
Siapa yang mempunyai akses | Pengubah suai | Contoh |
---|---|---|
Hanya saya | persendirian | Jurnal peribadi |
Keluarga | (tiada pengubah suai) | Foto keluarga |
Keluarga dan waris | dilindungi | Harta pusaka keluarga |
Semua orang | awam | Kenangan |
"Ia sama seperti membayangkan bahawa kelas dalam pakej yang sama adalah sebahagian daripada satu keluarga."
"Saya juga ingin memberitahu anda beberapa nuansa menarik tentang kaedah mengatasi."
1) Pelaksanaan tersirat kaedah abstrak.
Katakan anda mempunyai kod berikut:
class Cat
{
public String getName()
{
return "Oscar";
}
}
Dan anda memutuskan untuk mencipta kelas Tiger yang mewarisi kelas ini dan menambah antara muka pada kelas baharu
class Cat
{
public String getName()
{
return "Oscar";
}
}
interface HasName
{
String getName();
int getWeight();
}
class Tiger extends Cat implements HasName
{
public int getWeight()
{
return 115;
}
}
Jika anda hanya melaksanakan semua kaedah yang hilang yang IntelliJ IDEA memberitahu anda untuk melaksanakan, kemudian anda mungkin menghabiskan masa yang lama mencari pepijat.
Ternyata kelas Tiger mempunyai kaedah getName yang diwarisi daripada Cat, yang akan diambil sebagai pelaksanaan kaedah getName untuk antara muka HasName.
"Saya tidak nampak apa-apa yang mengerikan tentang itu."
"Ia tidak terlalu teruk, ia adalah tempat yang mungkin berlaku untuk kesilapan."
Tetapi ia boleh menjadi lebih teruk lagi:
interface HasWeight
{
int getValue();
}
interface HasSize
{
int getValue();
}
class Tiger extends Cat implements HasWeight, HasSize
{
public int getValue()
{
return 115;
}
}
Ternyata anda tidak selalu boleh mewarisi daripada berbilang antara muka. Lebih tepat lagi, anda boleh mewarisinya, tetapi anda tidak boleh melaksanakannya dengan betul. Tengok contoh. Kedua-dua antara muka memerlukan anda melaksanakan kaedah getValue(), tetapi tidak jelas apa yang harus dikembalikan: berat atau saiz? Perkara ini agak tidak menyenangkan untuk dihadapi.
"Saya setuju. Anda ingin melaksanakan kaedah, tetapi anda tidak boleh. Anda telah mewarisi kaedah dengan nama yang sama dari kelas asas. Ia rosak."
"Tetapi ada berita baik."
2) Meluaskan penglihatan. Apabila anda mewarisi jenis, anda boleh mengembangkan keterlihatan kaedah. Begini rupanya:
kod Java | Penerangan |
---|---|
|
|
|
Kami telah mengembangkan keterlihatan kaedah daripada protected kepada public . |
Kod | Mengapa ini "sah" |
---|---|
|
Semuanya hebat. Di sini kita tidak tahu bahawa keterlihatan telah dilanjutkan dalam kelas keturunan. |
|
Di sini kita memanggil kaedah yang keterlihatan telah dilanjutkan.
Jika ini tidak mungkin, kami sentiasa boleh mengisytiharkan kaedah dalam Tiger: Dalam erti kata lain, kami tidak bercakap tentang sebarang pelanggaran keselamatan. |
|
Sekiranya semua syarat yang diperlukan untuk memanggil kaedah dalam kelas asas ( Cat ) dipenuhi, maka mereka pasti berpuas hati untuk memanggil kaedah pada jenis keturunan ( Harimau ) . Kerana sekatan pada panggilan kaedah adalah lemah, tidak kuat. |
"Saya tidak pasti saya faham sepenuhnya, tetapi saya akan ingat bahawa ini mungkin."
3) Menyempitkan jenis pulangan.
Dalam kaedah yang diganti, kita boleh menukar jenis pulangan kepada jenis rujukan yang disempitkan.
kod Java | Penerangan |
---|---|
|
|
|
Kami mengatasi kaedah getMyParent , dan kini ia mengembalikan Tiger objek. |
Kod | Mengapa ini "sah" |
---|---|
|
Semuanya hebat. Di sini kita tidak tahu bahawa jenis pulangan kaedah getMyParent telah diluaskan dalam kelas keturunan.
Bagaimana «kod lama» berfungsi dan berfungsi. |
|
Di sini kita panggil kaedah yang jenis pulangannya telah disempitkan.
Jika ini tidak mungkin, kami sentiasa boleh mengisytiharkan kaedah dalam Tiger: Dalam erti kata lain, tiada pelanggaran keselamatan dan/atau jenis pelanggaran pemutus. |
|
Dan semuanya berfungsi dengan baik di sini, walaupun kami meluaskan jenis pembolehubah kepada kelas asas (Cat).
Kerana mengatasi, kaedah setMyParent yang betul dipanggil. Dan tiada apa yang perlu dibimbangkan apabila memanggil kaedah getMyParent , kerana nilai pulangan, walaupun kelas Tiger, masih boleh diberikan kepada pembolehubah myParent bagi kelas asas (Cat) tanpa sebarang masalah. Objek harimau boleh disimpan dengan selamat dalam kedua-dua pembolehubah Harimau dan pembolehubah Cat. |
"Ya. Faham. Apabila mengatasi kaedah, anda perlu mengetahui cara semua ini berfungsi jika kita menghantar objek kita kepada kod yang hanya boleh mengendalikan kelas asas dan tidak tahu apa-apa tentang kelas kita. "
"Tepat sekali! Kemudian persoalan besarnya ialah mengapa kita tidak boleh mengecilkan jenis nilai pulangan apabila mengatasi kaedah?"
"Sudah jelas bahawa dalam kes ini kod dalam kelas asas akan berhenti berfungsi:"
kod Java | Penjelasan masalah |
---|---|
|
|
|
Kami membebankan kaedah getMyParent dan mengecilkan jenis nilai pulangannya.
Semuanya baik-baik saja di sini. |
|
Kemudian kod ini akan berhenti berfungsi.
Kaedah getMyParent boleh mengembalikan sebarang contoh Objek, kerana ia sebenarnya dipanggil pada objek Harimau. Dan kami tidak mempunyai cek sebelum tugasan. Oleh itu, kemungkinan besar pembolehubah myParent jenis Cat akan menyimpan rujukan String. |
"Contoh yang bagus, Amigo!"
Di Jawa, sebelum kaedah dipanggil, tiada pemeriksaan sama ada objek itu mempunyai kaedah sedemikian. Semua semakan berlaku pada masa jalan. Dan panggilan [hipotesis] kepada kaedah yang hilang kemungkinan besar akan menyebabkan program cuba untuk melaksanakan kod bait yang tidak wujud. Ini akhirnya akan membawa kepada ralat maut, dan sistem pengendalian akan menutup program secara paksa.
"Wah. Sekarang saya tahu."
GO TO FULL VERSION