Apakah metode statis diwarisi di Java?

148

Saya sedang membaca Panduan Programmer untuk Sertifikasi SCJP Java ™ oleh Khalid Mughal.

Di bab Warisan, dijelaskan itu

Warisan anggota terkait erat dengan aksesibilitas yang mereka nyatakan. Jika anggota superclass dapat diakses dengan nama sederhananya di subclass (tanpa menggunakan sintaks tambahan seperti super), anggota itu dianggap mewarisi.

Itu juga menyebutkan bahwa metode statis tidak diwariskan. Tetapi kode di bawah ini sangat bagus:

class A
{
    public static void display()
    {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A
{
    public void show()
    {
        // This works - accessing display() by its simple name -
        // meaning it is inherited according to the book.
        display();
    }
}

Bagaimana saya bisa langsung menggunakan display()di kelas B? Bahkan lebih, B.display()juga berhasil.

Apakah penjelasan buku hanya berlaku untuk metode contoh?

Ahli algoritma
sumber
stackoverflow.com/questions/4716040/… memiliki info menarik.
Mat
Bukan itu yang tertulis di salinan saya, edisi pertama. Berikan kutipan yang sebenarnya.
Marquis dari Lorne

Jawaban:

183

Semua metode yang dapat diakses diwarisi oleh subclass.

Dari Tutorial Sun Java :

Sebuah subclass mewarisi semua publik dan anggota yang dilindungi dari induknya, tidak peduli di paket apa subclass itu berada. Jika subclass berada dalam paket yang sama dengan induknya, itu juga mewarisi anggota paket-private dari induknya. Anda dapat menggunakan anggota yang diwariskan sebagaimana adanya, menggantinya, menyembunyikannya, atau menambahnya dengan anggota baru

Satu-satunya perbedaan dengan metode statis (kelas) yang diwarisi dan metode non-statis (instance) yang diwarisi adalah bahwa saat Anda menulis metode statis baru dengan tanda tangan yang sama, metode statis lama hanya disembunyikan, tidak diganti.

Dari halaman tentang perbedaan antara mengganti dan menyembunyikan.

Perbedaan antara menyembunyikan dan menimpa memiliki implikasi penting. Versi metode yang diganti yang dipanggil adalah versi yang ada di subkelas. Versi metode tersembunyi yang dipanggil bergantung pada apakah metode tersebut dipanggil dari superclass atau subclass

yincrash
sumber
jadi inherited berhubungan dengan apakah kita bisa mengganti anggota itu di subkelas?
Algorithmist
Ya, itu bagian dari warisan, tapi tidak semuanya. Saya akan mengatakan bagian utama lainnya dari warisan adalah penggunaan kembali kode dan polimorfisme.
yincrash
Apakah redefining juga memiliki beberapa aturan seperti yang dimiliki overriding?
Surender Thakran
2
@Algorist tidak tidak persis. Semua hal yang dilihat subclass Anda lebih jauh dalam hierarki, adalah hal-hal yang diwarisi oleh kelas Anda. Tetapi metode statis yang diwarisi, tidak dapat diganti, hanya disembunyikan ("dideklarasikan ulang" dengan tanda tangan yang sama). Oleh karena itu, Anda juga dapat mendeklarasikan metode statis Anda sebagai final, tidak masalah. Metode statis mana yang akan dipanggil diketahui pada waktu kompilasi. Dengan metode instans non-final, resolusi harus ditangguhkan ke waktu proses karena dapat diganti.
Martin Andersson
1
Paragraf terakhir Anda benar-benar dirusak !!! "Versi metode penggantian yang dipanggil adalah yang ada di subkelas" ini tidak benar: Katakanlah: Versi metode penggantian yang dipanggil hanya ditentukan dalam waktu proses oleh JVM yang terkait dengan objek mana yang telah membuat hubungi :)
mounaim
16

Anda dapat mengalami perbedaan dalam kode berikut, yang merupakan sedikit modifikasi pada kode Anda.

class A {
    public static void display() {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A {
    public void show() {
        display();
    }

    public static void display() {
        System.out.println("Inside static method of this class");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // prints: Inside static method of this class
        b.display();

        A a = new B();
        // prints: Inside static method of superclass
        a.display();
    }
}

Hal ini karena metode statis adalah metode kelas.

A.display () dan B.display () akan memanggil metode kelas masing-masing.

Gaurav
sumber
1
Memanggil metode statis pada contoh seperti yang Anda coba tidak akan berfungsi di java.
Lucas C. Feijo
Itulah yang dijelaskan oleh program ini, membuat instance objek B dan mengharapkan pewarisan berfungsi tidak dapat dilakukan dengan anggota statis. Coba ambil kode yang sama di eclipse / ide apa pun atau kompilasi menggunakan javac dan jalankan
Gaurav
3
@ LucasC.Feijo sebenarnya saya itu berhasil. Setidaknya di IDE saya (eclipse). Saya baru saja mendapat peringatan. Ini mungkin bukan gaya yang bagus ... tapi itu cerita yang berbeda.
dingalapadum
3
@ LucasC.Feijo memanggil metode statis pada sebuah instance tidak disarankan. Tetapi cara kerjanya sama seperti memanggil metode statis pada nama kelas.
Ziyang Zhang
14

Jika itu yang sebenarnya dikatakan buku itu, itu salah. [1]

The Java Language Specification # 8.4.8 negara:

8.4.8 Warisan, Mengesampingkan, dan Menyembunyikan

Kelas C mewarisi dari superclass langsungnya semua metode konkret m (baik statis maupun instance) dari superclass yang semua hal berikut ini benar:

  • m adalah anggota kelas super langsung C.

  • m bersifat publik, dilindungi, atau dideklarasikan dengan akses paket dalam paket yang sama dengan C.

  • Tidak ada metode yang dideklarasikan di C yang memiliki tanda tangan yang merupakan subsignature (§8.4.2) dari tanda tangan m.

[1] Tidak disebutkan dalam salinan saya, edisi pertama, 2000.

Marquis dari Lorne
sumber
5

B.display () berfungsi karena deklarasi statik membuat metode / anggota menjadi milik kelas, dan bukan instance kelas tertentu (alias Objek). Anda dapat membaca lebih lanjut di sini .

Hal lain yang perlu diperhatikan adalah Anda tidak dapat mengganti metode statis, Anda dapat meminta subkelas Anda mendeklarasikan metode statis dengan tanda tangan yang sama, tetapi perilakunya mungkin berbeda dari yang Anda harapkan. Ini mungkin alasan mengapa tidak dianggap sebagai warisan. Anda dapat melihat skenario bermasalah dan penjelasannya di sini .

Kai
sumber
4

Metode statis di Java diwariskan, tetapi tidak dapat diganti. Jika Anda mendeklarasikan metode yang sama dalam subclass, Anda menyembunyikan metode superclass alih-alih menimpanya. Metode statis tidak polimorfik. Pada saat kompilasi, metode statis akan ditautkan secara statis.

Contoh:

public class Writer {
    public static void write() {
        System.out.println("Writing");
    }
}

public class Author extends Writer {
    public static void write() {
        System.out.println("Writing book");
    }
}

public class Programmer extends Writer {

    public static void write() {
        System.out.println("Writing code");
    }

    public static void main(String[] args) {
        Writer w = new Programmer();
        w.write();

        Writer secondWriter = new Author();
        secondWriter.write();

        Writer thirdWriter = null;
        thirdWriter.write();

        Author firstAuthor = new Author();
        firstAuthor.write();
    }
}

Anda akan mendapatkan yang berikut ini:

Writing
Writing
Writing
Writing book

sumber
2

Metode statis diwariskan di Java tetapi tidak mengambil bagian dalam polimorfisme. Jika kita mencoba untuk menimpa metode statik, mereka hanya akan menyembunyikan metode statik superclass daripada menimpanya.

Praveen Kumar
sumber
Saya tidak melihat alasan untuk meremehkan jawaban ini. Ini tajam & jelas, setidaknya bagian pertama. Bagian kedua tidak boleh diambil terlalu teknis, jika tidak tidak apa-apa. Untuk memperjelas, dalam metode penggantian, tipe pengembalian dapat berubah (menjadi sub-tipe) sedangkan ini tidak terjadi dengan metode statis. Secara teknis 'upaya untuk menimpa' tidak berlaku untuk metode statis, jadi yang bisa kami katakan adalah kami tidak bisa.
sharhp
2

Konsep ini tidak semudah kelihatannya. Kita dapat mengakses anggota statis tanpa pewarisan, yaitu hubungan-HasA. Kita dapat mengakses anggota statis dengan memperluas kelas induk juga. Itu tidak menyiratkan bahwa itu adalah relasi ISA (Warisan). Sebenarnya anggota statis adalah milik kelas, dan statis bukanlah pengubah akses. Selama pengubah akses mengizinkan untuk mengakses anggota statis, kita dapat menggunakannya di kelas lain. Seperti jika bersifat publik maka akan dapat diakses di dalam paket yang sama dan juga di luar paket. Untuk pribadi kami tidak dapat menggunakannya di mana pun. Secara default, kami hanya dapat menggunakannya di dalam paket. Tapi untuk melindungi kita harus memperluas kelas super. Jadi mendapatkan metode statis ke kelas lain tidak bergantung pada status Statis. Itu tergantung pada pengubah Access. Jadi menurut saya, Anggota statis dapat mengakses jika pengubah akses mengizinkan. Jika tidak, kita dapat menggunakannya seperti yang kita gunakan oleh relasi Hasa. Dan memiliki hubungan bukan warisan. Sekali lagi kami tidak dapat mengganti metode statis. Jika kita dapat menggunakan metode lain tetapi tidak dapat menimpanya, maka itu adalah hubungan-HasA. Jika kita tidak bisa menimpanya, itu tidak akan menjadi warisan, jadi penulisnya 100% benar.

Noman_ibrahim
sumber
Memperluas kelas induk adalah hubungan 'is-a'. Jika aksesnya pribadi, Anda dapat menggunakannya dari dalam kelas. 'protected' mencakup kelas turunan dan kelas dalam paket saat ini. Terlalu banyak kesalahan di sini.
Marquis dari Lorne
0

Metode statis diturunkan dalam subclass tetapi bukan polimorfisme. Saat Anda menulis implementasi metode statis, metode kelas induknya disembunyikan, bukan diganti. Pikirkan, jika tidak diwariskan lalu bagaimana Anda dapat mengakses tanpa classname.staticMethodname();?

pengguna4016405
sumber
0

Semua anggota publik dan yang dilindungi dapat diwarisi dari kelas mana pun sementara anggota default atau paket juga dapat diwarisi dari kelas dalam paket yang sama dengan kelas super. Itu tidak tergantung apakah itu anggota statis atau non statis.

Tetapi juga benar bahwa fungsi anggota statis tidak mengambil bagian dalam pengikatan dinamis. Jika tanda tangan dari metode statis tersebut sama di kelas induk dan anak maka konsep Shadowing berlaku, bukan polimorfisme.

shubham
sumber
0

Anda dapat mengganti metode statis, tetapi jika Anda mencoba menggunakan polimorfisme, metode tersebut bekerja sesuai dengan cakupan kelas (Bertentangan dengan yang biasanya kita harapkan).

public class A {

    public static void display(){
        System.out.println("in static method of A");
    }
}

public class B extends A {

    void show(){
        display();
    }

     public static void display(){
        System.out.println("in static method of B");
    }

}
public class Test {

    public static void main(String[] args){
        B obj =new B();
        obj.show();

        A a_obj=new B();
        a_obj.display();


    }


}

DALAM kasus pertama, o / p adalah "dalam metode statis B" # berhasil menimpa Dalam kasus kedua, o / p adalah "dalam metode statis A" # Metode statis - tidak akan mempertimbangkan polimorfisme

Manav Garekar
sumber
-1

Kita dapat mendeklarasikan metode statis dengan tanda tangan yang sama di subclass, tetapi itu tidak dianggap menimpa karena tidak akan ada polimorfisme run-time. Karena semua anggota statis kelas dimuat pada saat pemuatan kelas, jadi putuskan saat kompilasi waktu (overriding at run time) Oleh karena itu jawabannya adalah 'Tidak'.

NGK
sumber
2
Entah kenapa orang selalu down-voting dan tidak memberi alasan down voting.
surajs1n
Jawaban ini tentang menimpa. Pertanyaannya adalah tentang warisan.
Marquis dari Lorne
-1

Banyak yang menyuarakan jawaban mereka dengan kata-kata. Ini adalah penjelasan tambahan dalam kode:

public class A {
    public static void test() {
        System.out.println("A");
    }
    public static void test2() {
        System.out.println("Test");
    }
}

public class B extends A {
    public static void test() {
        System.out.println("B");
    }
}

// Called statically
A.test();
B.test();
System.out.println();

// Called statically, testing static inheritance
A.test2();
B.test2();
System.out.println();

// Called via instance object
A a = new A();
B b = new B();
a.test();
b.test();
System.out.println();

// Testing inheritance via instance call
a.test2();
b.test2();
System.out.println();

// Testing whether calling static method via instance object is dependent on compile or runtime type
((A) b).hi();
System.out.println();

// Testing whether null instance works
A nullObj = null;
nullObj.hi();

Hasil:

A
B

Test
Test

A
B

Test
Test

A

A

Karena itu, inilah kesimpulannya:

  1. Ketika kita memanggil statik secara statik via., Itu akan mencari statik yang didefinisikan di kelas itu, atau kelas yang terdekat dengan yang ada di rantai pewarisan. Ini membuktikan bahwa metode statis diwariskan.
  2. Ketika metode statis dipanggil dari sebuah instance, itu memanggil metode statis yang ditentukan dalam tipe waktu kompilasi.
  3. Metode statis dapat dipanggil dari sebuah nullinstance. Dugaan saya adalah bahwa kompilator akan menggunakan tipe variabel untuk menemukan kelas selama kompilasi, dan menerjemahkannya ke panggilan metode statis yang sesuai.
Jai
sumber
1
Kode belaka bukanlah penjelasan, ini adalah demonstrasi. Jawaban atas pertanyaan ini harus mengutip referensi normatif, bukan hanya menunjukkan perilaku implementasi yang tidak dinyatakan.
Marquis dari Lorne
-2

Anggota statis adalah anggota universal. Mereka bisa diakses dari mana saja.

Pavan
sumber
4
dapat diakses dari mana saja secara harfiah, yaitu salah: statis! = cakupan. Anda mungkin ingin mengklarifikasi :-)
kleopatra
Sebenarnya, jawaban ini baik-baik saja jika dipahami secara harfiah. Saya tidak dapat memikirkan satu tempat pun dalam kode di mana kode dapat pergi yang tidak dapat diakses oleh anggota statis kelas. Anda dapat mengaksesnya di penginisialisasi statis, konstruktor statis, konstruktor instance, metode, properti, di kelas yang berbeda, dalam cakupan apa pun. Selama kelas dan metode statis bersifat publik, mereka dapat diakses dari mana saja, dengan asumsi tidak ada ketergantungan melingkar pada penginisialisasi statis. Intinya, anggota statis tidak diwariskan, mereka hanya metode tingkat kelas (yaitu universal) yang dapat diakses dari mana saja.
Triynko
@Triynko Jawabannya salah dalam kasus metode yang privat, atau dilindungi paket diakses dari luar paket.
Marquis dari Lorne
@kleopatra - di luar topik. ayunan java? apakah orang benar-benar menggunakannya hari ini?
MasterJoe
@Pavan coba panggil private static dari luar kelas. Ini tidak akan berhasil.
Rakesh Yadav
-3

Anggota statis tidak akan diturunkan ke subkelas karena pewarisan hanya untuk anggota non-statis .. Dan anggota statis akan dimuat di dalam kumpulan statis oleh pemuat kelas. Pewarisan hanya untuk anggota yang dimuat di dalam objek

Ashwini E
sumber
Benar-benar salah. Lihat JLS # 8.4.8 .
Marquis dari Lorne
salah, perbarui jawaban Anda jika Anda jelas sekarang :)
iprashant