class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
Fungsi doIt akan mencetak "ayah". Apakah ada cara untuk membuatnya mencetak "anak"?
java
inheritance
overriding
Dikla
sumber
sumber
Jawaban:
Iya. Tetapi karena variabel yang bersangkutan itu ditimpa (Memberikan nilai baru ke variabel. Memberikan definisi baru untuk fungsi adalah Override).
Just don't declare the variable but initialize (change) in the constructor or static block.
Nilai akan tercermin ketika menggunakan di blok kelas induk
jika variabel statis maka ubah nilai selama inisialisasi itu sendiri dengan blok statis,
atau perubahan konstruktor.
Anda juga dapat mengubah nilai nanti di blok mana pun. Itu akan tercermin di kelas super
sumber
class Son extends Dad { static { me = 'son' } }
Singkatnya, tidak, tidak ada cara untuk mengganti variabel kelas.
Anda tidak menimpa variabel kelas di Jawa yang Anda sembunyikan. Overriding misalnya adalah metode. Menyembunyikan berbeda dari mengganti.
Dalam contoh yang Anda berikan, dengan mendeklarasikan variabel kelas dengan nama 'saya' di kelas Son, Anda menyembunyikan variabel kelas yang akan diwarisi dari ayah superclassnya dengan nama yang sama 'saya'. Menyembunyikan variabel dengan cara ini tidak mempengaruhi nilai variabel kelas 'saya' di superclass Dad.
Untuk bagian kedua dari pertanyaan Anda, bagaimana membuatnya mencetak "nak", saya akan menetapkan nilainya melalui konstruktor. Meskipun kode di bawah ini sangat berbeda dengan pertanyaan awal Anda, saya akan menulisnya seperti ini;
JLS memberikan lebih banyak detail tentang persembunyian di bagian 8.3 - Deklarasi Lapangan
sumber
Person
seharusnya diganti dalam contoh ini?Son
danDad
seharusnya mewarisi dariPerson
, lalu memanggilsuper("Son or Dad");
konstruktor mereka.Ya, cukup timpa
printMe()
metode ini:sumber
printMe()
metode, atau bahkan memiliki metode itu, itu adalah metode statis?Anda dapat membuat pengambil dan menimpa pengambil itu. Ini sangat berguna jika variabel yang Anda override adalah sub-kelas dari dirinya sendiri. Bayangkan kelas super Anda memiliki
Object
anggota tetapi di sub-kelas Anda ini sekarang lebih didefinisikan sebagaiInteger
.sumber
Jika Anda akan menimpanya, saya tidak melihat alasan yang valid untuk menjaga ini statis. Saya akan menyarankan penggunaan abstraksi (lihat kode contoh). :
Sekarang kita bisa menambahkan Dad:
anak laki-laki:
dan Ayah bertemu seorang wanita baik:
Sepertinya kita memiliki keluarga, mari beri tahu dunia nama mereka:
}
Output System.out: Tommy Nancy Dad
System.err sama seperti di atas (hanya memiliki font merah)
Output JOption:
Tommy lalu
Nancy lalu
Dad
sumber
Ini terlihat seperti cacat desain.
Hapus kata kunci statis dan atur variabel misalnya dalam konstruktor. Dengan cara ini Son hanya menetapkan variabel ke nilai yang berbeda di konstruktornya.
sumber
Meskipun benar bahwa variabel kelas hanya dapat disembunyikan di subclass, dan tidak diganti, masih mungkin untuk melakukan apa yang Anda inginkan tanpa menimpa
printMe ()
subclass, dan refleksi adalah teman Anda. Dalam kode di bawah ini saya menghilangkan penanganan pengecualian untuk kejelasan. Harap dicatat bahwa menyatakanme
sebagaiprotected
tampaknya tidak memiliki banyak akal dalam konteks ini, seperti yang akan disembunyikan di subclass ...sumber
... akan mencetak "nak".
sumber
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
Ini disebut Menyembunyikan Bidang
Dari tautan di atas
sumber
hanya dengan mengganti
printMe()
:referensi
me
dalamDad.printMe
metode ini secara implisit menunjuk ke bidang statisDad.me
, jadi dengan satu atau lain cara Anda mengubah apa yangprintMe
dilakukan diSon
...sumber
Anda tidak bisa menimpa variabel di kelas. Anda hanya dapat mengganti metode. Anda harus merahasiakan variabelnya jika tidak, Anda bisa mendapatkan banyak masalah.
sumber
Ini memang mencetak 'ayah', karena bidangnya tidak diganti tetapi disembunyikan. Ada tiga pendekatan untuk membuatnya mencetak 'anak':
Pendekatan 1: ganti printMe
Pendekatan 2: jangan sembunyikan bidang dan inisialisasi di konstruktor
Pendekatan 3: gunakan nilai statis untuk menginisialisasi bidang dalam konstruktor
sumber
Variabel tidak ikut serta dalam overrinding. Hanya metode yang melakukannya. Panggilan metode diselesaikan pada saat runtime, yaitu, keputusan untuk memanggil metode diambil pada saat runtime, tetapi variabel diputuskan pada waktu kompilasi saja. Oleh karena itu variabel dipanggil yang referensi digunakan untuk memanggil dan bukan dari objek runtime.
Lihatlah cuplikan berikut:
Saat Anda menjalankan kode, konsol akan menunjukkan:
sumber
Tentu saja menggunakan atribut pribadi, dan getter dan setter akan menjadi hal yang disarankan untuk dilakukan, tetapi saya menguji yang berikut, dan berfungsi ... Lihat komentar dalam kode
Sooo ... apakah saya baru saja mendefinisikan kembali aturan warisan atau apakah saya menempatkan Oracle ke dalam situasi yang rumit? Bagi saya, static String me yang terproteksi jelas diganti, seperti yang Anda lihat ketika Anda menjalankan program ini. Juga, tidak masuk akal bagi saya mengapa atribut tidak boleh ditimpa.
sumber
Mengapa Anda ingin menimpa variabel ketika Anda dapat dengan mudah menetapkan kembali mereka di subClasses.
Saya mengikuti pola ini untuk mengerjakan desain bahasa. Asumsikan sebuah kasus di mana Anda memiliki kelas layanan yang berat dalam kerangka kerja Anda yang perlu digunakan dalam rasa yang berbeda di beberapa aplikasi turunan. Dalam kasus itu, cara terbaik untuk mengkonfigurasi logika kelas super adalah dengan menetapkan kembali variabel 'mendefinisikan' nya.
sumber
Tidak. Variabel kelas (Juga berlaku untuk variabel instan) tidak menunjukkan fitur utama dalam Java karena variabel kelas dipanggil berdasarkan jenis objek panggilan. Menambahkan satu kelas lagi (Manusia) dalam hierarki untuk membuatnya lebih jelas. Jadi sekarang sudah
Putra meluas Ayah melebar Manusia
Dalam kode di bawah ini, kami mencoba untuk beralih di atas array objek Manusia, Ayah dan Anak, tetapi mencetak nilai Kelas Manusia dalam semua kasus karena jenis objek panggilan adalah Manusia.
Akan dicetak
Jika kita ingin mengakses variabel kelas dari objek aktual dari variabel referensi dari kelas induknya, kita perlu secara eksplisit mengatakan ini ke kompiler dengan casting referensi induk (objek Manusia) ke tipenya.
Akan dicetak
Pada bagian bagaimana pertanyaan ini: - Seperti yang sudah disarankan menimpa metode printMe () di kelas Son, kemudian pada panggilan
Variabel Kelas Ayah "aku" akan disembunyikan karena deklarasi terdekat (dari metode printme Kelas Anak) dari "aku" (di kelas Son) akan mendapatkan prioritas.
sumber
Panggil saja super.variable di konstruktor sub kelas
Outputnya adalah 10.
sumber