Mengapa Java tidak mengizinkan penggantian metode statis?

534

Mengapa tidak mungkin mengganti metode statis?

Jika memungkinkan, silakan gunakan contoh.

sgokhales
sumber
3
Sebagian besar bahasa OOP tidak mengizinkan ini.
jmucchiello
7
@ jmucchiello: lihat jawaban saya. Saya berpikir sama seperti Anda, tetapi kemudian belajar tentang metode 'kelas' Ruby / Smalltalk dan ada bahasa OOP sejati lainnya yang melakukan ini.
Kevin Brock
5
@jmucchiello kebanyakan bahasa OOP bukan bahasa OOP yang asli (saya pikir Smalltalk)
mathk
Lihat juga stackoverflow.com/q/370962/632951
Pacerier
1
mungkin karena Java menyelesaikan panggilan ke metode statis pada waktu kompilasi. Jadi, bahkan jika Anda telah menulis Parent p = new Child()dan kemudian p.childOverriddenStaticMethod()kompiler akan menyelesaikannya Parent.childOverriddenStaticMethod()dengan melihat tipe referensi.
Manoj

Jawaban:

494

Overriding tergantung pada memiliki instance kelas. Inti dari polimorfisme adalah bahwa Anda dapat mensubclass sebuah kelas dan objek yang mengimplementasikan subclass tersebut akan memiliki perilaku yang berbeda untuk metode yang sama yang didefinisikan dalam superclass (dan diganti dalam subclass). Metode statis tidak terkait dengan instance kelas apa pun sehingga konsepnya tidak berlaku.

Ada dua pertimbangan yang mendorong desain Java yang memengaruhi hal ini. Salah satunya adalah kekhawatiran dengan kinerja: ada banyak kritik terhadap Smalltalk tentang itu terlalu lambat (pengumpulan sampah dan panggilan polimorfik menjadi bagian dari itu) dan pencipta Jawa bertekad untuk menghindari itu. Lain adalah keputusan bahwa target audiens untuk Java adalah pengembang C ++. Membuat metode statis bekerja seperti yang mereka lakukan memiliki manfaat keakraban untuk programmer C ++ dan juga sangat cepat, karena tidak perlu menunggu sampai runtime untuk mengetahui metode mana yang harus dipanggil.

Nathan Hughes
sumber
18
... tetapi hanya "benar" di Jawa. Misalnya, Scala setara dengan "kelas statis" (yang disebut objects) memungkinkan kelebihan metode.
32
Objective-C juga memungkinkan metode kelas utama .
Richard
11
Ada hierarki tipe kompilasi-waktu dan hierarki tipe run-time. Sangat masuk akal untuk bertanya mengapa pemanggilan metode statis tidak memanfaatkan hierarki jenis run-time dalam keadaan di mana ada satu. Di Jawa ini terjadi ketika memanggil metode statis dari objek ( obj.staticMethod()) - yang diizinkan dan menggunakan tipe waktu kompilasi. Ketika panggilan statis dalam metode non-statis kelas, objek "saat ini" bisa menjadi tipe turunan kelas - tetapi metode statis yang didefinisikan pada tipe turunan tidak dipertimbangkan (mereka berada dalam tipe run-time hirarki).
Steve Powell
18
Saya seharusnya menjelaskan: tidak benar bahwa konsep itu tidak berlaku .
Steve Powell
13
Jawaban ini, walaupun benar, lebih mirip dengan "apa adanya" daripada bagaimana seharusnya atau lebih tepatnya bagaimana bisa untuk memenuhi harapan OP dan, karenanya di sini, saya dan orang lain. Tidak ada alasan konkret untuk melarang override metode statis selain "begitulah adanya". Saya pikir ini adalah kesalahan pribadi.
RichieHH
186

Secara pribadi saya pikir ini adalah cacat dalam desain Java. Ya, ya, saya mengerti bahwa metode non-statis dilampirkan ke instance sementara metode statis dilampirkan ke kelas, dll. Namun, pertimbangkan kode berikut:

public class RegularEmployee {
    private BigDecimal salary;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }

    public BigDecimal calculateBonus() {
        return salary.multiply(getBonusMultiplier());
    }

    /* ... presumably lots of other code ... */
}

public class SpecialEmployee extends RegularEmployee {
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

Kode ini tidak akan berfungsi seperti yang Anda harapkan. Yakni, SpecialEmployee's mendapatkan bonus 2% seperti halnya karyawan biasa. Tetapi jika Anda menghapus "statis", maka SpecialEmployee's mendapatkan bonus 3%.

(Harus diakui, contoh ini adalah gaya pengkodean yang buruk karena dalam kehidupan nyata Anda mungkin ingin pengganda bonus berada di basis data di suatu tempat daripada di-kode-keras. Tapi itu hanya karena saya tidak ingin mengurangi contoh dengan banyak kode tidak relevan dengan intinya.)

Tampaknya masuk akal bagi saya bahwa Anda mungkin ingin menjadikan getBonusMultiplier statis. Mungkin Anda ingin dapat menampilkan pengganda bonus untuk semua kategori karyawan, tanpa harus memiliki instance karyawan di setiap kategori. Apa gunanya mencari contoh contoh seperti itu? Bagaimana jika kita membuat kategori karyawan baru dan belum memiliki karyawan yang ditugaskan? Ini secara logis merupakan fungsi statis.

Tapi itu tidak berhasil.

Dan ya, ya, saya bisa memikirkan sejumlah cara untuk menulis ulang kode di atas untuk membuatnya berfungsi. Maksud saya bukanlah menciptakan masalah yang tidak dapat diselesaikan, tetapi menciptakan jebakan bagi programmer yang tidak waspada, karena bahasa tersebut tidak berperilaku seperti yang saya kira orang yang masuk akal harapkan.

Mungkin jika saya mencoba menulis kompiler untuk bahasa OOP, saya akan segera melihat mengapa mengimplementasikannya sehingga fungsi statis dapat ditimpa akan sulit atau tidak mungkin.

Atau mungkin ada beberapa alasan bagus mengapa Jawa berlaku seperti ini. Adakah yang bisa menunjukkan keunggulan perilaku ini, beberapa kategori masalah yang dibuat lebih mudah dengan ini? Maksud saya, jangan hanya mengarahkan saya ke spesifikasi bahasa Java dan mengatakan "lihat, ini didokumentasikan bagaimana perilakunya". Saya tahu itu. Tetapi apakah ada alasan bagus mengapa itu HARUS berperilaku seperti ini? (Selain itu jelas "membuatnya bekerja dengan benar terlalu sulit" ...)

Memperbarui

@VicKirk: Jika Anda maksudkan ini adalah "desain yang buruk" karena tidak sesuai dengan bagaimana Java menangani statika, jawaban saya adalah, "Ya, tentu saja, ya." Seperti yang saya katakan di posting asli saya, itu tidak berfungsi. Tetapi jika Anda maksudkan bahwa itu adalah desain yang buruk dalam arti bahwa akan ada sesuatu yang secara fundamental salah dengan bahasa tempat ini bekerja, yaitu di mana statika dapat ditimpa seperti fungsi virtual, bahwa ini entah bagaimana akan memperkenalkan ambiguitas atau tidak mungkin untuk menerapkan secara efisien atau semacamnya, saya menjawab, "Mengapa? Apa yang salah dengan konsep itu?"

Saya pikir contoh yang saya berikan adalah hal yang sangat alami untuk ingin dilakukan. Saya memiliki kelas yang memiliki fungsi yang tidak bergantung pada data instance apa pun, dan yang saya mungkin ingin sebut independen dari sebuah instance, serta ingin menelepon dari dalam metode instance. Mengapa ini tidak berhasil? Saya telah mengalami situasi ini beberapa kali selama bertahun-tahun. Dalam praktiknya saya menyiasatinya dengan membuat fungsi virtual, dan kemudian membuat metode statis yang satu-satunya tujuan dalam hidup adalah menjadi metode statis yang meneruskan panggilan ke metode virtual dengan contoh dummy. Itu sepertinya cara yang sangat bundaran untuk sampai ke sana.

Jay
sumber
11
@ Bromrose: Tapi itu maksud saya: Mengapa saya tidak boleh melakukan itu? Mungkin konsep intuitif saya tentang apa yang "statis" harus lakukan berbeda dari Anda, tetapi pada dasarnya saya menganggap statis sebagai metode yang BISA statis karena tidak menggunakan data contoh apa pun, dan yang HARUS statis karena Anda mungkin ingin untuk menyebutnya secara independen dari sebuah instance. Statis jelas terikat ke kelas: Saya berharap Integer.valueOf diikat ke Integer dan Double.valueOf diikat ke Doubles.
Jay
9
@ewernli & Bemrose: Ya ya, begitulah caranya. Saya tidak memperdebatkan itu. Karena kode dalam contoh saya tidak berfungsi, tentu saja saya tidak akan mencoba untuk menulisnya. Pertanyaan saya adalah mengapa demikian. (Saya khawatir ini berubah menjadi salah satu percakapan di mana kami tidak berkomunikasi. "Maaf Pak Salesman, bisakah saya mendapatkannya dengan warna merah?" "Tidak, biayanya $ 5." "Ya, saya tahu harganya. $ 5, tetapi bisakah saya mendapatkan yang merah? "" Pak, saya baru saja memberi tahu Anda bahwa harganya $ 5. "" Oke, saya tahu harganya, tetapi saya bertanya tentang warnanya. "" Saya sudah memberi tahu Anda harganya! " dll)
Jay
6
Saya pikir pada akhirnya kode ini membingungkan. Pertimbangkan jika instance dilewatkan sebagai parameter. Kemudian Anda mengatakan bahwa contoh runtime harus menentukan metode statis mana yang disebut. Itu pada dasarnya membuat seluruh hierarki terpisah sejajar dengan contoh yang ada. Sekarang bagaimana jika subclass mendefinisikan metode tanda tangan yang sama dengan non-statis? Saya pikir aturan itu akan membuat segalanya menjadi rumit. Justru jenis-jenis komplikasi bahasa inilah yang coba dihindari oleh Jawa.
Yishai
6
@Yishai: RE "Runtime instance menentukan metode statis mana yang disebut": Tepat. Saya tidak melihat mengapa Anda tidak dapat melakukan apa pun dengan statis yang dapat Anda lakukan dengan virtual. "Hirarki terpisah": Saya katakan, Jadikan itu bagian dari hierarki yang sama. Mengapa statika tidak termasuk dalam hierarki yang sama? "Subsclass mendefinisikan tanda tangan yang sama non-statis": Saya menganggap itu ilegal, seperti ilegal untuk, katakanlah, memiliki subclass yang menimpa fungsi dengan tanda tangan yang identik tetapi jenis pengembalian yang berbeda, atau untuk tidak membuang semua pengecualian yang induk melempar, atau memiliki ruang lingkup yang lebih sempit.
Jay
28
Saya pikir Jay ada benarnya - itu mengejutkan saya juga ketika saya menemukan bahwa statika tidak dapat ditimpa. Sebagian karena jika saya memiliki metode A dengan someStatic()dan B meluas A, maka B.someMethod() mengikat ke metode dalam A. Jika saya kemudian menambahkan someStatic()ke B, kode panggilan masih memanggil A.someStatic()sampai saya mengkompilasi ulang kode panggilan. Juga itu mengejutkan saya bahwa bInstance.someStatic()menggunakan menyatakan jenis bInstance, bukan tipe runtime karena mengikat di kompilasi tidak link sehingga A bInstance; ... bInstance.someStatic()memanggil A.someStatic () jika jika B.someStatic () ada.
Lawrence Dol
42

Jawaban singkatnya adalah: itu sepenuhnya mungkin, tetapi Java tidak melakukannya.

Berikut adalah beberapa kode yang menggambarkan keadaan terkini di Jawa:

File Base.java:

package sp.trial;
public class Base {
  static void printValue() {
    System.out.println("  Called static Base method.");
  }
  void nonStatPrintValue() {
    System.out.println("  Called non-static Base method.");
  }
  void nonLocalIndirectStatMethod() {
    System.out.println("  Non-static calls overridden(?) static:");
    System.out.print("  ");
    this.printValue();
  }
}

File Child.java:

package sp.trial;
public class Child extends Base {
  static void printValue() {
    System.out.println("  Called static Child method.");
  }
  void nonStatPrintValue() {
    System.out.println("  Called non-static Child method.");
  }
  void localIndirectStatMethod() {
    System.out.println("  Non-static calls own static:");
    System.out.print("  ");
    printValue();
  }
  public static void main(String[] args) {
    System.out.println("Object: static type Base; runtime type Child:");
    Base base = new Child();
    base.printValue();
    base.nonStatPrintValue();
    System.out.println("Object: static type Child; runtime type Child:");
    Child child = new Child();
    child.printValue();
    child.nonStatPrintValue();
    System.out.println("Class: Child static call:");
    Child.printValue();
    System.out.println("Class: Base static call:");
    Base.printValue();
    System.out.println("Object: static/runtime type Child -- call static from non-static method of Child:");
    child.localIndirectStatMethod();
    System.out.println("Object: static/runtime type Child -- call static from non-static method of Base:");
    child.nonLocalIndirectStatMethod();
  }
}

Jika Anda menjalankan ini (saya melakukannya di Mac, dari Eclipse, menggunakan Java 1.6) Anda akan mendapatkan:

Object: static type Base; runtime type Child.
  Called static Base method.
  Called non-static Child method.
Object: static type Child; runtime type Child.
  Called static Child method.
  Called non-static Child method.
Class: Child static call.
  Called static Child method.
Class: Base static call.
  Called static Base method.
Object: static/runtime type Child -- call static from non-static method of Child.
  Non-static calls own static.
    Called static Child method.
Object: static/runtime type Child -- call static from non-static method of Base.
  Non-static calls overridden(?) static.
    Called static Base method.

Di sini, satu - satunya kasus yang mungkin mengejutkan (dan yang menjadi pertanyaan adalah) adalah kasus pertama :

"Tipe run-time tidak digunakan untuk menentukan metode statis mana yang dipanggil, bahkan ketika dipanggil dengan instance objek ( obj.staticMethod())."

dan kasus terakhir :

"Ketika memanggil metode statis dari dalam metode objek kelas, metode statis yang dipilih adalah yang dapat diakses dari kelas itu sendiri dan bukan dari kelas yang mendefinisikan jenis run-time objek."

Memanggil dengan instance objek

Panggilan statis diselesaikan pada waktu kompilasi, sedangkan panggilan metode non-statis diselesaikan pada saat dijalankan. Perhatikan bahwa meskipun metode statis diwariskan (dari orangtua) mereka tidak diganti (oleh anak). Ini bisa menjadi kejutan jika Anda mengharapkan sebaliknya.

Memanggil dari dalam metode objek

Panggilan metode objek diselesaikan menggunakan tipe run-time, tetapi panggilan metode statis ( kelas ) diselesaikan dengan menggunakan tipe waktu kompilasi (dideklarasikan).

Mengubah aturan

Untuk mengubah aturan-aturan ini, sehingga panggilan terakhir dalam contoh yang dipanggil Child.printValue(), panggilan statis harus disediakan dengan tipe pada saat run-time, daripada kompiler menyelesaikan panggilan pada saat kompilasi dengan kelas objek yang dideklarasikan (atau konteks). Panggilan statis kemudian dapat menggunakan hirarki tipe (dinamis) untuk menyelesaikan panggilan, seperti yang dilakukan metode panggilan objek hari ini.

Ini dengan mudah bisa dilakukan (jika kita mengubah Java: -O), dan sama sekali tidak masuk akal, bagaimanapun, ia memiliki beberapa pertimbangan menarik.

Pertimbangan utama adalah bahwa kita perlu memutuskan panggilan metode statis mana yang harus melakukan ini.

Saat ini, Java memiliki "kekhasan" dalam bahasa di mana obj.staticMethod()panggilan diganti dengan ObjectClass.staticMethod()panggilan (biasanya dengan peringatan). [ Catatan: ObjectClass adalah tipe waktu kompilasi obj.] Ini akan menjadi kandidat yang baik untuk mengganti dengan cara ini, dengan menggunakan tipe run-time obj.

Jika kita lakukan itu akan membuat badan metode lebih sulit untuk dibaca: panggilan statis di kelas induk berpotensi secara dinamis "dialihkan kembali". Untuk menghindari ini, kita harus memanggil metode statis dengan nama kelas - dan ini membuat panggilan lebih jelas diselesaikan dengan hierarki jenis waktu kompilasi (seperti sekarang).

Cara lain untuk menggunakan metode statis lebih rumit: this.staticMethod()harus berarti sama dengan obj.staticMethod(), mengambil jenis run-time this. Namun, ini dapat menyebabkan beberapa sakit kepala dengan program yang ada, yang memanggil metode statis (tampaknya lokal) tanpa dekorasi (yang bisa dibilang setara dengan this.method()).

Jadi bagaimana dengan panggilan tanpa hiasan staticMethod()? Saya menyarankan mereka melakukan hal yang sama seperti hari ini, dan menggunakan konteks kelas lokal untuk memutuskan apa yang harus dilakukan. Kalau tidak, akan timbul kebingungan besar. Tentu saja itu berarti bahwa method()akan berarti this.method()jika methoditu metode non-statis, dan ThisClass.method()jika methoditu metode statis. Ini adalah sumber kebingungan lainnya.

Pertimbangan lainnya

Jika kami mengubah perilaku ini (dan membuat panggilan statis yang berpotensi non-lokal secara dinamis), kami mungkin ingin meninjau kembali makna final, privatedan protectedsebagai kualifikasi pada staticmetode kelas. Kita kemudian harus membiasakan diri dengan fakta bahwa private staticdan public finalmetode tidak diganti, dan karena itu dapat diselesaikan dengan aman pada waktu kompilasi, dan "aman" untuk dibaca sebagai referensi lokal.

Steve Powell
sumber
"Jika kita melakukannya akan membuat badan metode lebih sulit untuk dibaca: panggilan statis di kelas induk berpotensi secara dinamis" dialihkan kembali "." Benar, tapi inilah yang terjadi dengan panggilan fungsi non-statis biasa sekarang. Ini secara rutin disebut-sebut sebagai fitur positif untuk fungsi virtual biasa, bukan masalah.
Jay
25

Sebenarnya kami salah.
Meskipun Java tidak memungkinkan Anda untuk menimpa metode statis secara default, jika Anda melihat dengan teliti melalui dokumentasi kelas dan metode kelas di Jawa, Anda masih bisa menemukan cara untuk meniru metode statis menimpa dengan mengikuti solusi berikut:

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;

class RegularEmployee {

    private BigDecimal salary = BigDecimal.ONE;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }
    public BigDecimal calculateBonus() {
        return salary.multiply(this.getBonusMultiplier());
    }
    public BigDecimal calculateOverridenBonus() {
        try {
            // System.out.println(this.getClass().getDeclaredMethod(
            // "getBonusMultiplier").toString());
            try {
                return salary.multiply((BigDecimal) this.getClass()
                    .getDeclaredMethod("getBonusMultiplier").invoke(this));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }
    // ... presumably lots of other code ...
}

final class SpecialEmployee extends RegularEmployee {

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

public class StaticTestCoolMain {

    static public void main(String[] args) {
        RegularEmployee Alan = new RegularEmployee();
        System.out.println(Alan.calculateBonus());
        System.out.println(Alan.calculateOverridenBonus());
        SpecialEmployee Bob = new SpecialEmployee();
        System.out.println(Bob.calculateBonus());
        System.out.println(Bob.calculateOverridenBonus());
    }
}

Output yang dihasilkan:

0.02
0.02
0.02
0.03

apa yang kami coba capai :)

Bahkan jika kita mendeklarasikan variabel ketiga Carl sebagai RegularEmployee dan menugaskan contoh SpecialEmployee, kita masih akan memiliki panggilan metode RegularEmployee dalam kasus pertama dan panggilan metode SpecialEmployee dalam kasus kedua

RegularEmployee Carl = new SpecialEmployee();

System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());

lihat saja konsol keluaran:

0.02
0.03

;)

Patlatus
sumber
9
Ya refleksi adalah satu-satunya hal yang dapat dilakukan - tetapi pertanyaannya tidak persis seperti ini - berguna untuk memilikinya di sini
Mr_and_Mrs_D
1
Jawaban ini adalah retasan terbesar yang pernah saya lihat sejauh ini di semua topik Java. Sangat menyenangkan untuk membacanya :)
Andrejs
19

Metode statis diperlakukan sebagai global oleh JVM, tidak ada terikat pada contoh objek sama sekali.

Secara konseptual dapat dimungkinkan jika Anda dapat memanggil metode statis dari objek kelas (seperti dalam bahasa seperti Smalltalk) tetapi tidak demikian halnya di Jawa.

EDIT

Anda dapat membebani metode statis, tidak apa-apa. Tetapi Anda tidak dapat mengganti metode statis, karena kelas bukan objek kelas satu. Anda bisa menggunakan refleksi untuk mendapatkan kelas dari suatu objek pada saat run-time, tetapi objek yang Anda dapatkan tidak sejajar dengan hierarki kelas.

class MyClass { ... }
class MySubClass extends MyClass { ... }

MyClass obj1 = new MyClass();
MySubClass obj2 = new MySubClass();

ob2 instanceof MyClass --> true

Class clazz1 = obj1.getClass();
Class clazz2 = obj2.getClass();

clazz2 instanceof clazz1 --> false

Anda dapat merefleksikan kelas, tetapi berhenti di sana. Anda tidak menggunakan metode statis dengan menggunakan clazz1.staticMethod(), tetapi menggunakan MyClass.staticMethod(). Metode statis tidak terikat pada objek dan karenanya tidak ada gagasan tentang thisatau superdalam metode statis. Metode statis adalah fungsi global; sebagai konsekuensinya juga tidak ada gagasan polimorfisme dan, oleh karena itu, metode penimpaan tidak masuk akal.

Tapi ini bisa dimungkinkan jika MyClassada objek saat run-time di mana Anda memanggil metode, seperti dalam Smalltalk (atau mungkin JRuby sebagai satu komentar menyarankan, tapi saya tidak tahu apa-apa tentang JRuby).

Oh ya, satu hal lagi. Anda dapat menggunakan metode statis melalui objek obj1.staticMethod()tetapi itu benar-benar sintaksis untuk MyClass.staticMethod()dan harus dihindari. Biasanya memunculkan peringatan dalam IDE modern. Saya tidak tahu mengapa mereka pernah mengizinkan pintasan ini.

ewernli
sumber
5
Bahkan banyak bahasa modern seperti Ruby memiliki metode kelas dan memungkinkan untuk menimpanya.
Chandra Sekar
3
Kelas memang ada sebagai objek di Jawa. Lihat kelas "Kelas". Saya dapat mengatakan myObject.getClass () dan itu akan mengembalikan saya sebuah instance dari objek kelas yang sesuai.
Jay
5
Anda hanya mendapatkan "deskripsi" kelas - bukan kelas itu sendiri. Tetapi perbedaannya halus.
ewernli
Anda masih memiliki kelas tetapi tersembunyi di VM (dekat loader kelas), pengguna hampir tidak memiliki akses ke sana.
mathk
Untuk menggunakan clazz2 instanceof clazz1dengan benar, Anda dapat menggunakan class2.isAssignableFrom(clazz1), yang saya percaya akan mengembalikan true dalam contoh Anda.
Simon Forsberg
14

Metode penimpaan dimungkinkan oleh pengiriman dinamis , yang berarti bahwa jenis objek yang dideklarasikan tidak menentukan perilakunya, melainkan jenis runtime-nya:

Animal lassie = new Dog();
lassie.speak(); // outputs "woof!"
Animal kermit = new Frog();
kermit.speak(); // outputs "ribbit!"

Meskipun keduanya lassiedan kermitdideklarasikan sebagai objek bertipe Animal, perilaku (metode .speak()) mereka bervariasi karena pengiriman dinamis hanya akan mengikat pemanggilan metode .speak()pada implementasi pada saat run time - bukan pada waktu kompilasi.

Sekarang, di sinilah statickata kunci mulai masuk akal: kata "statis" adalah antonim untuk "dinamis". Jadi alasan mengapa Anda tidak dapat mengganti metode statis adalah karena tidak ada pengiriman dinamis pada anggota statis - karena statis secara harfiah berarti "tidak dinamis". Jika mereka dikirim secara dinamis (dan dengan demikian bisa ditimpa) statickata kunci tidak akan masuk akal lagi.

Richard JP Le Guen
sumber
11

Iya. Praktis Java memungkinkan metode statis utama, dan Tidak secara teoritis jika Anda menimpa metode statis di Jawa maka itu akan mengkompilasi dan berjalan dengan lancar tetapi akan kehilangan Polimorfisme yang merupakan properti dasar Jawa. Anda akan Baca Di Mana Saja bahwa tidak mungkin untuk mencoba membuat dan menjalankan sendiri. Anda akan mendapatkan jawaban Anda. mis. Jika Anda Memiliki Hewan Kelas dan metode statis, makan () dan Anda Override metode statis itu dalam Subkelasnya, beri nama Dog. Kemudian ketika di mana pun Anda Menetapkan objek Anjing ke Referensi Hewan dan memanggil eat () menurut Java Dog eat () seharusnya dipanggil tetapi dalam makan Overriding Animals statis () akan Dipanggil.

class Animal {
    public static void eat() {
        System.out.println("Animal Eating");
    }
}

class Dog extends Animal{
    public static void eat() {
        System.out.println("Dog Eating");
    }
}

class Test {
    public static void main(String args[]) {
       Animal obj= new Dog();//Dog object in animal
       obj.eat(); //should call dog's eat but it didn't
    }
}


Output Animal Eating

Menurut Prinsip Polimorfisme Jawa, Keluaran Seharusnya Dog Eating.
Tetapi hasilnya berbeda karena untuk mendukung Polymorphism Java menggunakan Late Binding yang berarti metode hanya dipanggil pada saat run-time tetapi tidak dalam kasus metode statis. Dalam metode statis, kompiler memanggil metode pada waktu kompilasi daripada pada saat run-time, jadi kami mendapatkan metode sesuai dengan referensi dan tidak sesuai dengan objek referensi yang mengandung itu sebabnya Anda dapat mengatakan Secara praktis mendukung overring statis tetapi secara teoritis, tidak 't.

Shubham Soni
sumber
3
Ini praktik buruk untuk memanggil metode statis dari objek.
Dmitry Zagorulkin
6

overriding dicadangkan untuk anggota misalnya untuk mendukung perilaku polimorfik. anggota kelas statis bukan milik instance tertentu. sebagai gantinya, anggota statis menjadi anggota kelas dan akibatnya pengesampingan tidak didukung karena subkelas hanya mewarisi anggota yang dilindungi dan publik dan bukan anggota statis. Anda mungkin ingin mendefinisikan pabrik inerface dan riset dan / atau pola desain strategi untuk mengevaluasi pendekatan alternatif.

Athens Holloway
sumber
1
Apakah Anda tidak membaca jawaban lain yang sudah membahas hal ini dan membuatnya jelas bahwa ini bukan alasan yang cukup untuk mengabaikan statika override pada tingkat konseptual. Kami tahu itu tidak berhasil. Sangat "bersih untuk menginginkan
penggantian
Richard, mari kita asumsikan sejenak bahwa ketika saya menanggapi pertanyaan ini 4 tahun yang lalu sebagian besar jawaban ini belum diposting, jadi jangan keledai! Tidak perlu menegaskan bahwa saya tidak membaca dengan cermat. Selain itu, apakah Anda tidak membaca bahwa kami hanya membahas pengesampingan sehubungan dengan Java. Siapa yang peduli apa yang mungkin dilakukan dalam bahasa lain. Itu tidak relevan. Pergi troll di tempat lain. Komentar Anda tidak menambahkan nilai apa pun pada utas ini.
Athens Holloway
6

Di Jawa (dan banyak bahasa OOP, tapi saya tidak bisa berbicara untuk semua; dan beberapa tidak memiliki statis sama sekali) semua metode memiliki tanda tangan tetap - parameter dan tipe. Dalam metode virtual, parameter pertama tersirat: referensi ke objek itu sendiri dan ketika dipanggil dari dalam objek, kompiler secara otomatis menambahkanthis .

Tidak ada perbedaan untuk metode statis - mereka masih memiliki tanda tangan tetap. Namun, dengan mendeklarasikan metode statis, Anda telah secara eksplisit menyatakan bahwa kompiler tidak boleh menyertakan parameter objek tersirat pada awal tanda tangan itu. Oleh karena itu, kode lain apa pun yang memanggil ini harus tidak boleh mencoba untuk menempatkan referensi ke objek di tumpukan . Jika memang melakukan itu, maka eksekusi metode tidak akan bekerja karena parameter akan berada di tempat yang salah - digeser oleh satu - di stack.

Karena perbedaan antara keduanya; Metode virtual selalu memiliki referensi ke objek konteks (yaitu this) sehingga maka dimungkinkan untuk referensi apa pun di dalam tumpukan yang dimiliki oleh instance objek tersebut. Tetapi dengan metode statis, karena tidak ada referensi yang lewat, metode itu tidak dapat mengakses variabel objek dan metode apa pun karena konteksnya tidak diketahui.

Jika Anda berharap bahwa Java akan mengubah definisi sehingga konteks objek diteruskan untuk setiap metode, statis atau virtual, maka Anda pada dasarnya hanya memiliki metode virtual.

Ketika seseorang bertanya dalam komentar pada op - apa alasan dan tujuan Anda menginginkan fitur ini?

Saya tidak tahu banyak tentang Ruby, karena ini disebutkan oleh OP, saya melakukan riset. Saya melihat bahwa di kelas Ruby benar-benar jenis objek khusus dan seseorang dapat membuat (bahkan secara dinamis) metode baru. Kelas adalah objek kelas penuh di Ruby, mereka bukan di Jawa. Ini adalah sesuatu yang harus Anda terima ketika bekerja dengan Java (atau C #). Ini bukan bahasa dinamis, meskipun C # menambahkan beberapa bentuk dinamis. Pada kenyataannya, Ruby tidak memiliki metode "statis" sejauh yang saya bisa temukan - dalam hal ini adalah metode pada objek kelas singleton. Anda kemudian dapat menimpa singleton ini dengan kelas baru dan metode di objek kelas sebelumnya akan memanggil yang didefinisikan di kelas baru (benar?). Jadi jika Anda memanggil metode dalam konteks kelas asli itu masih hanya akan menjalankan statika asli, tetapi memanggil metode dalam kelas turunan, akan memanggil metode baik dari induk atau sub-kelas. Menarik dan saya bisa melihat beberapa nilai di dalamnya. Dibutuhkan pola pikir yang berbeda.

Karena Anda bekerja di Jawa, Anda harus menyesuaikan dengan cara melakukan hal-hal tersebut. Kenapa mereka melakukan ini? Yah, mungkin untuk meningkatkan kinerja pada saat itu berdasarkan pada teknologi dan pemahaman yang tersedia. Bahasa komputer terus berkembang. Kembalilah cukup jauh dan tidak ada yang namanya OOP. Di masa depan, akan ada ide-ide baru lainnya.

EDIT : Satu komentar lain. Sekarang saya melihat perbedaannya dan saya sebagai pengembang Java / C #, saya bisa mengerti mengapa jawaban yang Anda dapatkan dari pengembang Java mungkin membingungkan jika Anda berasal dari bahasa seperti Ruby. staticMetode Java tidak sama dengan classmetode Ruby . Pengembang Java akan mengalami kesulitan memahami hal ini, seperti halnya mereka yang kebanyakan bekerja dengan bahasa seperti Ruby / Smalltalk. Saya dapat melihat bagaimana ini juga akan sangat membingungkan dengan fakta bahwa Java juga menggunakan "metode kelas" sebagai cara lain untuk berbicara tentang metode statis tetapi istilah yang sama digunakan secara berbeda oleh Ruby. Java tidak memiliki metode kelas gaya Ruby (maaf); Ruby tidak memiliki metode statis gaya Java yang benar-benar hanya fungsi gaya prosedural lama, seperti yang ditemukan dalam C.

By the way - terima kasih atas pertanyaannya! Saya belajar sesuatu yang baru untuk saya hari ini tentang metode kelas (gaya Ruby).

Kevin Brock
sumber
1
Tentu saja, tidak ada alasan mengapa Java tidak bisa melewatkan objek "Kelas" sebagai parameter tersembunyi ke metode statis. Itu tidak dirancang untuk melakukannya.
jmucchiello
6

Yah ... jawabannya adalah TIDAK jika Anda berpikir dari perspektif bagaimana seharusnya metode overriden di Jawa. Tapi, Anda tidak mendapatkan kesalahan kompilator jika Anda mencoba mengganti metode statis. Itu berarti, jika Anda mencoba menimpa, Java tidak menghentikan Anda melakukan itu; tetapi Anda tentu tidak mendapatkan efek yang sama seperti yang Anda dapatkan untuk metode non-statis. Meng-override di Jawa berarti bahwa metode tertentu akan dipanggil berdasarkan jenis run time objek dan bukan pada tipe waktu kompilasi objek (yang merupakan kasus dengan metode statis overriden). Oke ... ada tebakan untuk alasan mengapa mereka berperilaku aneh? Karena mereka adalah metode kelas dan karenanya akses ke mereka selalu diselesaikan selama waktu kompilasi hanya menggunakan informasi tipe waktu kompilasi.

Contoh : mari kita coba lihat apa yang terjadi jika kita mencoba mengganti metode statis: -

class SuperClass {
// ......
public static void staticMethod() {
    System.out.println("SuperClass: inside staticMethod");
}
// ......
}

public class SubClass extends SuperClass {
// ......
// overriding the static method
public static void staticMethod() {
    System.out.println("SubClass: inside staticMethod");
}

// ......
public static void main(String[] args) {
    // ......
    SuperClass superClassWithSuperCons = new SuperClass();
    SuperClass superClassWithSubCons = new SubClass();
    SubClass subClassWithSubCons = new SubClass();

    superClassWithSuperCons.staticMethod();
    superClassWithSubCons.staticMethod();
    subClassWithSubCons.staticMethod();
    // ...
}
}

Output : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod

Perhatikan baris kedua dari output. Seandainya staticMethod di-override baris ini seharusnya identik dengan baris ketiga saat kita memanggil 'staticMethod ()' pada objek Runtime Type sebagai 'SubClass' dan bukan sebagai 'SuperClass'. Ini mengonfirmasi bahwa metode statis selalu diselesaikan menggunakan informasi jenis waktu kompilasi saja.

Rupesh Yadav
sumber
5

Secara umum tidak masuk akal untuk mengizinkan 'menimpa' metode statis karena tidak akan ada cara yang baik untuk menentukan mana yang akan dipanggil saat runtime. Mengambil contoh Karyawan, jika kita memanggil RegularEmployee.getBonusMultiplier () - metode mana yang seharusnya dijalankan?

Dalam kasus Jawa, orang dapat membayangkan definisi bahasa di mana dimungkinkan untuk 'menimpa' metode statis selama mereka dipanggil melalui instance objek. Namun, semua ini akan dilakukan adalah menerapkan kembali metode kelas reguler, menambahkan redundansi ke bahasa tanpa benar-benar menambahkan manfaat apa pun.

Lars
sumber
2
Secara intuitif, saya akan berpikir itu harus berfungsi seperti fungsi virtual. Jika B memanjang A dan A dan B memiliki fungsi virtual bernama doStuff, kompiler tahu bahwa instance A harus menggunakan A.doStuff dan instance B harus menggunakan B.doStuff. Mengapa tidak bisa melakukan hal yang sama dengan fungsi statis? Setelah semua, kompiler tahu kelas apa setiap objek adalah instance.
Jay
Erm ... Jay, metode statis tidak perlu (umumnya tidak) dipanggil pada contoh ...
meriton
2
@meriton, tapi itu lebih mudah, bukan? Jika metode statis dipanggil menggunakan nama kelas, Anda akan menggunakan metode yang sesuai untuk kelas tersebut.
CPerkins
Tapi lalu apa yang dilakukan untuk Anda. Jika Anda memanggil A.doStuff () sebaiknya menggunakan versi yang ditimpa dalam "B extends A" atau versi yang ditimpa dalam "C extends A". Dan jika Anda memiliki C atau B maka Anda memanggil versi itu ... tidak perlu mengesampingkan.
PSpeed
@meriton: Memang benar bahwa metode statis umumnya tidak dipanggil dengan sebuah instance, tapi saya kira itu karena panggilan seperti itu tidak berguna mengingat desain Java saat ini! Saya menyarankan bahwa desain alternatif mungkin ide yang lebih baik. BTW, dalam arti yang sangat nyata, fungsi statis dipanggil dengan instance cukup rutin: Ketika Anda memanggil fungsi statis dari dalam fungsi virtual. Maka Anda secara implisit mendapatkan this.function (), yaitu instance saat ini.
Jay
5

Dengan mengesampingkan kita dapat membuat sifat polimorfik tergantung pada jenis objek. Metode statis tidak ada hubungannya dengan objek. Jadi java tidak dapat mendukung metode statis utama.

DeveloperArnab
sumber
5

Saya suka dan gandakan komentar Jay ( https://stackoverflow.com/a/2223803/1517187 ).
Saya setuju bahwa ini adalah desain Java yang buruk.
Banyak bahasa lain mendukung metode statis utama, seperti yang kita lihat di komentar sebelumnya. Saya merasa Jay juga datang ke Jawa dari Delphi seperti saya.
Delphi (Object Pascal) adalah bahasa pertama yang mengimplementasikan OOP.
Jelas bahwa banyak orang memiliki pengalaman dengan bahasa itu karena di masa lalu hanya bahasa untuk menulis produk GUI komersial. Dan - ya, kita bisa mengesampingkan metode statis di Delphi. Sebenarnya, metode statis dalam Delphi disebut "metode kelas", sedangkan Delphi memiliki konsep yang berbeda "metode statis Delphi" yang merupakan metode dengan penjilidan awal. Untuk mengganti metode Anda harus menggunakan pengikatan akhir, mendeklarasikan direktif "virtual". Jadi itu sangat mudah dan intuitif dan saya harapkan ini di Jawa.

Patlatus
sumber
3

Apa gunanya mengganti metode statis. Anda tidak dapat memanggil metode statis melalui instance.

MyClass.static1()
MySubClass.static1()   // If you overrode, you have to call it through MySubClass anyway.

EDIT: Tampaknya melalui pengawasan yang tidak menguntungkan dalam desain bahasa, Anda dapat memanggil metode statis melalui instance. Umumnya tidak ada yang melakukan itu. Salahku.

fastcodejava
sumber
8
"Anda tidak dapat memanggil metode statis melalui instance" Sebenarnya, salah satu kebiasaan Java adalah Anda BISA memanggil metode statis melalui instance, meskipun itu adalah ide yang sangat buruk.
Powerlord
1
Memang Java memungkinkan anggota statis untuk diakses melalui instance: lihat variabel statis di Jawa
Richard JP Le Guen
IDE modern yang tepat akan menghasilkan peringatan ketika Anda melakukannya, jadi setidaknya Anda bisa menangkapnya sementara Oracle dapat menjaga kompatibilitas mundur berjalan.
Gimby
1
Secara konsep tidak ada yang salah dengan memanggil metode statis melalui instance. Ini kebawelan demi kebawelan. Mengapa sesuatu seperti instance Date TIDAK memanggil metode statisnya sendiri mengirimkan data instance ke fungsi melalui antarmuka panggilan?
RichieHH
@ RichieHH Bukan itu yang mereka bicarakan. Pertanyaannya adalah mengapa itu diizinkan untuk memanggil variable.staticMethod(), bukannya Class.staticMethod(), di mana variablevariabel dengan tipe yang dideklarasikan Class. Saya setuju itu desain bahasa yang buruk.
Fishinear
3

Overriding di Jawa berarti bahwa metode tertentu akan dipanggil berdasarkan pada tipe runtime objek dan bukan pada tipe waktu kompilasi (yang merupakan kasus dengan metode statis yang diganti). Karena metode statis adalah metode kelas, mereka bukan metode instan sehingga tidak ada hubungannya dengan fakta referensi mana yang menunjuk ke Objek atau instance mana, karena karena sifat metode statis itu milik kelas tertentu. Anda dapat mendeklarasikan ulang di subclass tetapi subclass itu tidak akan tahu apa-apa tentang metode statis kelas induk karena, seperti yang saya katakan, itu hanya khusus untuk kelas yang telah dideklarasikan. Mengakses mereka menggunakan referensi objek hanyalah kebebasan ekstra yang diberikan oleh perancang Jawa dan kita tentu tidak boleh berpikir untuk menghentikan praktik itu hanya ketika mereka membatasi lebih detail dan contoh http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html

faisalbhagat
sumber
3

Dengan mengesampingkan, Anda mencapai polimorfisme dinamis. Ketika Anda mengatakan metode statis utama, kata-kata yang Anda coba gunakan bertentangan.

Kata statis - waktu kompilasi, penggantian digunakan untuk polimorfisme dinamis. Keduanya sifatnya berlawanan, dan karenanya tidak dapat digunakan bersama.

Perilaku polimorfik dinamis muncul ketika seorang programmer menggunakan objek dan mengakses metode instance. JRE akan memetakan metode instance yang berbeda dari kelas yang berbeda berdasarkan pada jenis objek yang Anda gunakan.

Ketika Anda mengatakan mengganti metode statis, metode statis akan kita akses dengan menggunakan nama kelas, yang akan ditautkan pada waktu kompilasi, jadi tidak ada konsep menghubungkan metode saat runtime dengan metode statis. Jadi istilah "mengesampingkan" metode statis itu sendiri tidak ada artinya.

Catatan: bahkan jika Anda mengakses metode kelas dengan objek, masih kompiler java cukup cerdas untuk mengetahuinya, dan akan melakukan tautan statis.

pengguna1923551
sumber
Ini tidak benar dalam banyak contoh di mana pada saat runtime metode statis sebenarnya dipanggil dari turunan kelas yang mengandung dan dengan demikian sangat layak untuk menentukan contoh fungsi yang akan dipanggil.
RichieHH
statis tidak berarti waktu kompilasi, statis berarti terikat ke kelas daripada objek tertentu. masuk akal jika tidak lebih masuk akal daripada menciptakan pabrik kelas, kecuali statis Box.createBoxlebih masuk akal daripada BoxFactory.createBox, dan merupakan pola yang tidak dapat dihindari ketika perlu untuk memeriksa kesalahan konstruksi tanpa melemparkan pengecualian (konstruktor tidak dapat gagal, mereka hanya dapat mematikan proses / melempar pengecualian), sedangkan metode statis dapat mengembalikan nol pada kegagalan, atau bahkan menerima panggilan balik keberhasilan / kesalahan untuk menulis sesuatu seperti hastebin.com/codajahati.java .
Dmitry
2

Jawaban dari pertanyaan ini sederhana, metode atau variabel yang ditandai sebagai statis hanya milik kelas saja, sehingga metode statis tidak dapat diwariskan dalam sub kelas karena mereka hanya milik kelas super saja.

g1ji
sumber
1
Hai G4uKu3_Gaurav. Terima kasih telah memutuskan untuk berkontribusi. Namun kami biasanya mengharapkan jawaban yang lebih panjang dan lebih rinci dari ini.
DJClayworth
@DJClayworth Anda harus mengikuti tautan ini untuk jawaban terinci geeksforgeeks.org/...
g1ji
Terima kasih untuk tautannya. Sebenarnya saya di sini untuk membantu pendatang baru di situs ini, untuk menjelaskan cara kerja situs bagi mereka yang tidak terbiasa, bukan karena saya membutuhkan jawaban untuk pertanyaan itu.
DJClayworth
1

Solusi mudah: Gunakan instance singleton. Ini akan memungkinkan penggantian dan pewarisan.

Dalam sistem saya, saya memiliki kelas SingletonsRegistry, yang mengembalikan instance untuk Kelas yang lulus. Jika instance tidak ditemukan, itu dibuat.

Kelas bahasa Haxe:

package rflib.common.utils;
import haxe.ds.ObjectMap;



class SingletonsRegistry
{
  public static var instances:Map<Class<Dynamic>, Dynamic>;

  static function __init__()
  {
    StaticsInitializer.addCallback(SingletonsRegistry, function()
    {
      instances = null;
    });

  } 

  public static function getInstance(cls:Class<Dynamic>, ?args:Array<Dynamic>)
  {
    if (instances == null) {
      instances = untyped new ObjectMap<Dynamic, Dynamic>();      
    }

    if (!instances.exists(cls)) 
    {
      if (args == null) args = [];
      instances.set(cls, Type.createInstance(cls, args));
    }

    return instances.get(cls);
  }


  public static function validate(inst:Dynamic, cls:Class<Dynamic>)
  {
    if (instances == null) return;

    var inst2 = instances[cls];
    if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!";
  }

}
Raivo Fishmeister
sumber
Sangat keren, ini pertama kalinya saya mendengar tentang bahasa pemrograman Haxe :)
cyc115
1
Ini jauh lebih baik diimplementasikan di Jawa sebagai metode statis di kelas itu sendiri; Singleton.get(). Registri hanya overhead boilerplate, dan menghalangi GC di kelas.
Lawrence Dol
Anda benar, itu adalah solusi klasik. Saya tidak ingat persis mengapa saya memilih registri, mungkin memiliki beberapa kerangka pemikiran yang mengarah pada hasil ini.
Raivo Fishmeister
1

Metode statis, variabel, blok atau kelas bersarang milik seluruh kelas daripada objek.

Metode di Jawa digunakan untuk mengekspos perilaku Obyek / Kelas. Di sini, karena metode ini statis (yaitu, metode statis digunakan untuk mewakili perilaku kelas saja.) Mengubah / mengesampingkan perilaku seluruh kelas akan melanggar fenomena salah satu pilar dasar pemrograman berorientasi objek yaitu, kohesi tinggi . (ingat konstruktor adalah jenis metode khusus di Jawa.)

Kohesi Tinggi - Satu kelas seharusnya hanya memiliki satu peran. Sebagai contoh: Kelas mobil harus menghasilkan hanya objek mobil dan bukan sepeda, truk, pesawat dll. Tapi kelas Mobil mungkin memiliki beberapa fitur (perilaku) yang hanya dimiliki oleh dirinya sendiri.

Oleh karena itu, sambil merancang bahasa pemrograman java. Perancang bahasa berpikir untuk memungkinkan pengembang untuk menjaga perilaku kelas hanya dengan membuat metode statis.


Kode bagian di bawah ini mencoba menimpa metode statis, tetapi tidak akan menemukan kesalahan kompilasi.

public class Vehicle {
static int VIN;

public static int getVehileNumber() {
    return VIN;
}}

class Car extends Vehicle {
static int carNumber;

public static int getVehileNumber() {
    return carNumber;
}}

Ini karena, di sini kita tidak mengganti metode tetapi kita hanya mendeklarasikannya kembali. Java memungkinkan deklarasi ulang suatu metode (statis / non-statis).

Menghapus kata kunci statis dari metode getVehileNumber () kelas Mobil akan mengakibatkan kesalahan kompilasi, Karena, kami mencoba mengubah fungsionalitas metode statis yang hanya milik kelas Kendaraan.

Juga, Jika getVehileNumber () dideklarasikan sebagai final maka kode tidak akan dikompilasi, Karena kata kunci terakhir membatasi programmer dari menyatakan kembali metode.

public static final int getVehileNumber() {
return VIN;     }

Secara keseluruhan, ini adalah perancang perangkat lunak terkini untuk tempat menggunakan metode statis. Saya pribadi lebih suka menggunakan metode statis untuk melakukan beberapa tindakan tanpa membuat instance kelas apa pun. Kedua, menyembunyikan perilaku kelas dari dunia luar.

Rohit Gaikwad
sumber
1

Berikut ini penjelasan sederhana. Metode statis dikaitkan dengan kelas sedangkan metode contoh dikaitkan dengan objek tertentu. Override memungkinkan memanggil implementasi yang berbeda dari metode override yang terkait dengan objek tertentu. Jadi kontra-intuitif untuk menimpa metode statis yang bahkan tidak terkait dengan objek tetapi kelas itu sendiri di tempat pertama. Jadi metode statis tidak bisa diganti berdasarkan objek apa yang memanggilnya, itu akan selalu dikaitkan dengan kelas tempat ia dibuat.

Rafsan Mobasher
sumber
Bagaimana kontra intuitif untuk memiliki public abstract IBox createBox();antarmuka IBox di dalam? Box dapat mengimplementasikan IBox untuk mengesampingkan createBox, dan membuat kreasi objek menghasilkan IBox yang valid, jika tidak mengembalikan null. Konstruktor tidak dapat mengembalikan "null" dan karena itu Anda dipaksa untuk (1) menggunakan pengecualian di mana-mana (apa yang kita lakukan sekarang), atau (2) membuat kelas pabrik yang melakukan apa yang saya katakan sebelumnya tetapi dengan cara yang tidak masuk akal bagi pemula atau ahli Jawa (Yang kami juga lakukan sekarang). Metode statis yang tidak diimplementasikan menyelesaikan ini.
Dmitry
-1

Sekarang melihat jawaban di atas semua orang tahu bahwa kita tidak dapat menimpa metode statis, tetapi orang tidak boleh salah paham tentang konsep mengakses metode statis dari subclass .

Kita dapat mengakses metode statis kelas super dengan referensi subclass jika metode statis ini belum disembunyikan oleh metode statis baru yang didefinisikan dalam sub kelas.

Sebagai Contoh, lihat kode di bawah ini: -

public class StaticMethodsHiding {
    public static void main(String[] args) {
        SubClass.hello();
    }
}


class SuperClass {
    static void hello(){
        System.out.println("SuperClass saying Hello");
    }
}


class SubClass extends SuperClass {
    // static void hello() {
    // System.out.println("SubClass Hello");
    // }
}

Keluaran:-

SuperClass saying Hello

Lihat Java oracle docs dan cari What You Can Do di Subclass untuk perincian tentang menyembunyikan metode statis di sub kelas.

Terima kasih

amandeep1991
sumber
-3

Kode berikut menunjukkan bahwa itu mungkin:

class OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriden Meth");   
}   

}   

public class OverrideStaticMeth extends OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriding Meth");   
}   

public static void main(String[] args) {   
OverridenStaticMeth osm = new OverrideStaticMeth();   
osm.printValue();   

System.out.println("now, from main");
printValue();

}   

} 
tumpukan pop
sumber
1
Tidak, tidak; statis jenis dinyatakan osmadalah OverridenStaticMethtidak OverrideStaticMeth.
Lawrence Dol
2
Juga, saya akan mencoba untuk menghindari menggunakan Meth begitu banyak saat pemrograman <big cengiran>;
Lawrence Dol