Mengganti vs Menyembunyikan Java - Bingung


88

Saya bingung tentang perbedaan mengesampingkan dari bersembunyi di Jawa. Adakah yang bisa memberikan rincian lebih lanjut tentang perbedaannya? Saya membaca Tutorial Java tetapi kode contoh masih membuat saya bingung.

Untuk lebih jelasnya, saya memahami mengesampingkan dengan baik. Masalah saya adalah bahwa saya tidak melihat bagaimana menyembunyikan itu berbeda, kecuali fakta bahwa yang satu ada di tingkat contoh sementara yang lain ada di tingkat kelas.

Melihat kode tutorial Java:

public class Animal {
    public static void testClassMethod() {
        System.out.println("Class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance " + " method in Animal.");
    }
}

Kemudian kami memiliki subclass Cat:

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method" + " in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method" + " in Cat.");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

Lalu mereka berkata:

Output dari program ini adalah sebagai berikut:

Metode kelas pada Hewan.

Metode instance di Cat.

Bagi saya, fakta bahwa memanggil metode kelas testClassMethod()langsung dari Animalkelas menjalankan metode di Animalkelas cukup jelas, tidak ada yang istimewa di sana. Kemudian mereka memanggil testInstanceMethod()dari referensi ke myCat, jadi sekali lagi cukup jelas bahwa metode yang dieksekusi adalah yang ada di instance Cat.

Dari apa yang saya lihat, panggilan bersembunyi berperilaku seperti menimpa, jadi mengapa membuat perbedaan itu? Jika saya menjalankan kode ini menggunakan kelas-kelas di atas:

Cat.testClassMethod();

Saya akan mendapatkan: Metode kelas di Cat. Tetapi jika saya menghapus testClassMethod()dari Cat, maka saya akan mendapatkan: Metode kelas di Animal.

Yang menunjukkan kepada saya bahwa menulis metode statis, dengan tanda tangan yang sama seperti di induk, di subkelas cukup banyak melakukan penggantian.

Mudah-mudahan saya menjelaskan di mana saya bingung dan seseorang dapat menjelaskan. Terima kasih banyak sebelumnya!


Jawaban:


103

Overriding pada dasarnya mendukung pengikatan yang terlambat. Oleh karena itu, diputuskan pada saat berjalan metode mana yang akan dipanggil. Ini untuk metode non-statis.

Menyembunyikan adalah untuk semua anggota lainnya (metode statis, anggota instance, anggota statis). Ini didasarkan pada pengikatan awal. Lebih jelasnya, metode atau anggota yang akan dipanggil atau digunakan ditentukan selama waktu kompilasi.

Dalam contoh Anda, panggilan pertama, Animal.testClassMethod()adalah panggilan ke suatu staticmetode, oleh karena itu cukup yakin metode mana yang akan dipanggil.

Pada panggilan kedua myAnimal.testInstanceMethod(), Anda memanggil metode non-statis. Inilah yang Anda sebut polimorfisme run-time. Tidak diputuskan sampai waktu berjalan metode mana yang akan dipanggil.

Untuk klarifikasi lebih lanjut, baca Mengganti Vs Menyembunyikan .


3
Terima kasih atas jawaban cepatnya, ini menjelaskannya! Saya perhatikan bahwa dalam contoh JavaRanch, mereka menggunakan variabel untuk memanggil metode kelas alih-alih menggunakan kelas secara langsung yang membuatnya lebih mudah untuk dipahami. Saya kira di tutorial Java mereka menggunakan kelas secara langsung karena menggunakan sebuah instance untuk memanggil metode statis mungkin bukan praktik yang baik, tetapi mereka seharusnya menggunakan myAnimal.testClassMethod () daripada Animal.testClassMethod () .
Lostlinkpr

1 karena bisa menjelaskannya dengan kata-kata dengan benar, bukan dengan contoh! :)
WhyNotHugo

@Kazekage Gaara Apakah ada perbedaan antara kelebihan muatan dan menyembunyikan?
gstackoverflow

1
Saya setuju tentu saja dengan jawabannya, tapi bagaimana private methods? Mereka tidak mungkin overriddenkarena subclass tidak tahu tentang keberadaan mereka .. Oleh karena itu, mereka mungkin hiddensaja.
Paschalis

Jawaban Luar Biasa! Meskipun Anda dapat menambahkan contoh di coderanch demi kelengkapan :)
Shubham Mittal

19

Metode statis disembunyikan, metode non-statis diganti. Perbedaannya penting ketika panggilan tidak memenuhi syarat "sesuatu ()" vs "this.something ()".

Saya tidak bisa benar-benar meletakkannya pada kata-kata, jadi inilah contohnya:

public class Animal {

    public static void something() {
        System.out.println("animal.something");
    }

    public void eat() {
        System.out.println("animal.eat");
    }

    public Animal() {
        // This will always call Animal.something(), since it can't be overriden, because it is static.
        something();
        // This will call the eat() defined in overriding classes.
        eat();
    }

}


public class Dog extends Animal {

    public static void something() {
        // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way.
        System.out.println("dog.something");
    }

    public void eat() {
        // This method overrides eat(), and will affect calls to eat()
        System.out.println("dog.eat");
    }

    public Dog() {
        super();
    }

    public static void main(String[] args) {
        new Dog();
    }

}

KELUARAN:

animal.something
dog.eat

1
ok, lalu apa yang akan terjadi jika saya memanggil `dog husky = new dog (); ' dan sebut husky.Animal();apakah itu akan mencetak binatang.sesuatu atau anjing.sesuatu ? Saya kira SALAH untuk mengatakan ** bahwa ** Ini akan selalu memanggil Animal.something ()
amarnath harish

@amarnathharish Anda tidak dapat melakukannya .Animal(), ingat Animal()adalah konstruktor.
Dude156

Dan sebagai klarifikasi lebih lanjut bagi siapa pun yang bertanya-tanya, alasan something()in Animal() selalu memanggil Animal's something()adalah karena panggilan ke metode statis diselesaikan dalam waktu kompilasi daripada run-time. Ini berarti bahwa pemanggilan metode statis Animal()selalu secara implisit memanggil Animal.something(). Ini cukup intuitif jika Anda memikirkannya: panggilan ke metode statis harus diawali dengan nama kelas (yaitu className.staticMethodName()) kecuali panggilan tersebut berada di kelas yang sama.
Dude156

14

Inilah perbedaan antara menimpa dan menyembunyikan,

  1. Jika kedua metode di kelas induk dan kelas anak adalah metode instance, itu disebut overrides.
  2. Jika kedua metode di kelas induk dan kelas anak adalah metode statis, itu disebut menyembunyikan.
  3. Satu metode tidak boleh statis di orang tua dan sebagai instance di anak. dan sebaliknya.

masukkan deskripsi gambar di sini


3
Anda memotong dan menempelkan tabel itu langsung dari tutorial yang menurut OP tidak membantunya mengerti.
wolfcastle

Tabel membuatnya sangat jelas, dalam contoh tidak semua kasus dipertimbangkan.
tutak

3

Jika saya memahami pertanyaan Anda dengan benar maka jawabannya adalah "Anda sudah menimpa".

"Yang menunjukkan kepada saya bahwa menulis metode statis, dengan nama yang sama seperti di induk, dalam subkelas cukup banyak melakukan penggantian."

Jika Anda menulis metode dalam subclass dengan nama yang sama persis dengan metode di superclass, metode tersebut akan menimpa metode superclass. Anotasi @Override tidak diperlukan untuk mengganti metode. Namun itu membuat kode Anda lebih mudah dibaca dan memaksa compiler untuk memeriksa bahwa Anda benar-benar mengganti metode (dan tidak salah mengeja metode subclass misalnya).


1
Jawaban ini gagal untuk menjawab metode contoh vs statis terkait dengan penimpaan / penyembunyian.
Paul Bellora

3

Penggantian hanya terjadi dengan metode instance. Jika tipe variabel referensi adalah Hewan dan objeknya adalah Cat, maka metode instance dipanggil dari Cat (ini menimpa). Untuk objek acat yang sama metode kelas Animal digunakan.

public static void main(String[] args) {
    Animal acat = new Cat();
    acat.testInstanceMethod();
    acat.testClassMethod();

}

Outputnya adalah:

The instance method in Cat.
Class method in Animal.

2
public class First {

    public void Overriding(int i) {  /* will be overridden in class Second */ }

    public static void Hiding(int i) {  /* will be hidden in class Second
                                           because it's static */ }
}


public class Second extends First {

    public void Overriding(int i) {  /* overridden here */  }

    public static void Hiding(int i) {  /* hides method in class First
                                           because it's static */ } 
}

Aturan untuk menghafalnya sederhana: metode dalam kelas yang diperluas tidak dapat mengubah statis menjadi void dan tidak dapat mengubah void menjadi statis. Ini akan menyebabkan kesalahan kompilasi.

Tetapi jika void Namediubah menjadi void NameOverriding.

Dan jika static Namediubah menjadi static NameBersembunyi. (Baik metode statis subkelas maupun salah satu superclass dapat dipanggil, bergantung pada jenis referensi yang digunakan untuk memanggil metode tersebut.)


1

Dalam cuplikan kode ini saya menggunakan pengubah akses 'pribadi' alih-alih 'statis' untuk menunjukkan perbedaan antara metode penyembunyian dan metode penimpaan.

class Animal {
// Use 'static' or 'private' access modifiers to see how method hiding work.
private void testInstancePrivateMethod(String source) {
    System.out.println("\tAnimal: instance Private method calling from "+source);
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Private method.");
    testInstancePrivateMethod( Animal.class.getSimpleName() );
}

// Use default, 'protected' or 'public' access modifiers to see  how method overriding work.
protected void testInstanceProtectedMethod(String source) {
    System.out.println("\tAnimal: instance Protected method calling from "+source);
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Protected method.");
    testInstanceProtectedMethod( Animal.class.getSimpleName() );
  } 
}  


public class Cat extends Animal {
private void testInstancePrivateMethod(String source) {
    System.out.println("Cat: instance Private method calling from " + source );
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("Cat: instance Public method with using of Private method.");
    testInstancePrivateMethod( Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingPrivateMethodInside();
}

protected void testInstanceProtectedMethod(String source) {
    System.out.println("Cat: instance Protected method calling from "+ source );
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("Cat: instance Public method with using of Protected method.");
    testInstanceProtectedMethod(Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingProtectedMethodInside();
}

public static void main(String[] args) {
    Cat myCat = new Cat();
    System.out.println("----- Method hiding -------");
    myCat.testInstanceMethodUsingPrivateMethodInside();
    System.out.println("\n----- Method overriding -------");
    myCat.testInstanceMethodUsingProtectedMethodInside();
}
}

Keluaran:

----- Method hiding -------
Cat: instance Public method with using of Private method.
Cat: instance Private method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Private method.
   Animal: instance Private method calling from Animal

----- Method overriding -------
Cat: instance Public method with using of Protected method.
Cat: instance Protected method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Protected method.
Cat: instance Protected method calling from Animal

heran mengapa tidak mendapatkan upvote .. jawaban yang sangat dihargai.
Amarnath Harish

0

Berdasarkan studi Java saya baru-baru ini

  • metode overriding , ketika subclass memiliki metode yang sama dengan tanda tangan yang sama di subclass tersebut.
  • Metode persembunyian , ketika subclass memiliki nama metode yang sama, tetapi parameter yang berbeda. Dalam kasus ini, Anda tidak mengganti metode induk, tetapi menyembunyikannya.

Contoh dari buku OCP Java 7, halaman 70-71:

public class Point {
  private int xPos, yPos;
  public Point(int x, int y) {
        xPos = x;
        yPos = y;
  }

  public boolean equals(Point other){
  .... sexy code here ...... 
  }

  public static void main(String []args) {
   Point p1 = new Point(10, 20);
   Point p2 = new Point(50, 100);
   Point p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //point's class equals method get invoked
  }
}

tetapi jika kita menulis main berikut:

  public static void main(String []args) {
   Object p1 = new Point(10, 20);
   Object p2 = new Point(50, 100);
   Object p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //Object's class equals method get invoked
  }

Di main kedua, kami menggunakan kelas Object sebagai tipe statis, jadi ketika kami memanggil metode yang sama di objek Point, itu menunggu kelas Point untuk datang sebagai parameter, tapi Object datang. Jadi kelas Objek sama dengan metode yang dijalankan, karena kami memiliki sama dengan (Objek o) di sana. Dalam kasus ini, kelas Poin sama dengan dosen tidak menimpa, tetapi menyembunyikan metode kelas Objek sama dengan .


0
public class Parent {

  public static void show(){
    System.out.println("Parent");
  }
}

public class Child extends Parent{

  public static void show(){
    System.out.println("Child");
  }
}

public class Main {

public static void main(String[] args) {
    Parent parent=new Child();
    parent.show(); // it will call parent show method
  }
}

// We can call static method by reference ( as shown above) or by using class name (Parent.show())

0

Halaman tutorial java yang ditautkan menjelaskan konsep menimpa dan menyembunyikan

Metode instance dalam subclass dengan tanda tangan yang sama (nama, ditambah nomor dan tipe parameternya) dan tipe kembalian sebagai metode instance di superclass menimpa metode superclass.

Jika subclass mendefinisikan metode statis dengan tanda tangan yang sama sebagai metode statis di superclass, maka metode di subclass menyembunyikan metode di superclass.

Perbedaan antara menyembunyikan metode statis dan mengganti metode instance memiliki implikasi penting:

  1. Versi metode contoh yang diganti yang dipanggil adalah versi yang ada di subkelas.
  2. Versi metode statis tersembunyi yang dipanggil bergantung pada apakah metode tersebut dipanggil dari superclass atau subclass.

Kembali ke contoh Anda:

Animal myAnimal = myCat;

 /* invokes static method on Animal, expected. */
 Animal.testClassMethod(); 

 /* invokes child class instance method (non-static - it's overriding) */
 myAnimal.testInstanceMethod();

Pernyataan di atas belum menunjukkan persembunyian.

Sekarang ubah kode seperti di bawah ini untuk mendapatkan output yang berbeda:

  Animal myAnimal = myCat;
  
  /* Even though myAnimal is Cat, Animal class method is invoked instead of Cat method*/
  myAnimal.testClassMethod();
  
  /* invokes child class instance method (non-static - it's overriding) */
  myAnimal.testInstanceMethod();

Saya mencoba untuk memahami apa arti kata bersembunyi. Apa menyembunyikan apa? Apakah metode statis di kelas Parent tersembunyi karena (paling tidak diharapkan) itu dipanggil? Atau apakah metode statis di kelas Anak tersembunyi, karena tidak dipanggil?
kalajengking

0

Selain contoh yang tercantum di atas, berikut adalah contoh kode kecil untuk memperjelas perbedaan antara menyembunyikan dan mengganti:

public class Parent {

    // to be hidden (static)
    public static String toBeHidden() {
        return "Parent";
    }

    // to be overridden (non-static)
    public String toBeOverridden() {
        return "Parent";
    }

    public void printParent() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Child extends Parent {

    public static String toBeHidden() {
        return "Child";
    }

    public String toBeOverridden() {
        return "Child";
    }

    public void printChild() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Main {

    public static void main(String[] args) {
        Child child = new Child();
        child.printParent();
        child.printChild();
    }
}

Panggilan child.printParent()keluaran:
disembunyikan: Induk yang
akan diganti: Anak

Panggilan child.printChild()keluaran:
disembunyikan: Anak yang
akan diganti: Anak

Seperti yang bisa kita lihat dari output di atas (terutama output yang ditandai tebal), penyembunyian metode berperilaku berbeda dari penggantian.

Java memungkinkan menyembunyikan dan mengganti hanya untuk metode. Aturan yang sama tidak berlaku untuk variabel. Variabel pengganti tidak diizinkan, jadi variabel hanya dapat disembunyikan (tidak ada perbedaan antara variabel statis atau non-statis). Contoh di bawah ini menunjukkan bagaimana metode getName()tersebut diganti dan variabel namedisembunyikan:

public class Main {

    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.name); // prints Parent (since hiding)
        System.out.println(p.getName()); // prints Child (since overriding)
    }
}

class Parent {
    String name = "Parent";

    String getName() {
        return name;
    }
}

class Child extends Parent {
    String name = "Child";

    String getName() {
        return name;
    }
}

0

Pada waktu proses, versi turunan dari metode yang diganti selalu dieksekusi untuk sebuah instance terlepas dari apakah pemanggilan metode didefinisikan dalam metode kelas induk atau turunan. Dengan cara ini, metode induk tidak pernah digunakan kecuali panggilan eksplisit ke metode induk dirujuk, menggunakan sintaks ParentClassName.method (). Alternatifnya, pada waktu proses, versi induk dari metode tersembunyi selalu dijalankan jika panggilan ke metode ditentukan di kelas induk.


0

Dalam metode penggantian , resolusi metode dilakukan oleh JVM berdasarkan objek runtime. Sedangkan dalam penyembunyian metode, penyelesaian metode dilakukan oleh compiler berdasarkan referensi. Jadi,

Jika kodenya akan ditulis sebagai,

public static void main(String[] args) {
        Animal myCat = new Cat();        
        myCat.testClassMethod();        
    }

Outputnya akan seperti di bawah ini:
Metode kelas pada Hewan.


0

Disebut menyembunyikan karena kompilator menyembunyikan implementasi metode kelas super, ketika subkelas memiliki metode statis yang sama.

Compiler tidak memiliki visibilitas terbatas untuk metode yang diganti dan hanya selama runtime yang diputuskan mana yang digunakan.


0

Inilah perbedaan antara menimpa dan menyembunyikan:

Hewan a = Kucing baru ();

a.testClassMethod () akan memanggil metode di kelas induk karena ini adalah contoh dari metode yang disembunyikan. Metode yang akan dipanggil ditentukan oleh jenis variabel referensi dan diputuskan pada waktu kompilasi.

a.testInstanceMethod () akan memanggil metode dalam kelas anak karena ini adalah contoh dari penggantian metode. Metode yang dipanggil ditentukan oleh objek yang digunakan untuk memanggil metode saat runtime.


0

Saya pikir ini belum sepenuhnya dijelaskan. Silakan lihat contoh berikut.

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal");
    }
}


public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }

    public static void main(String[] args) {
        Animal myCat = new Cat();
        Cat myCat2 = new Cat();
        myCat.testClassMethod();
        myCat2.testClassMethod();
        
        
        myCat.testInstanceMethod();
        myCat2.testInstanceMethod();
    }
}

Outputnya adalah sebagai berikut.

The static method in Animal
The static method in Cat
The instance method in Cat
The instance method in Cat

-1

Bagaimana metode statis bersembunyi di java? Kelas kucing memperluas kelas Hewan. Jadi di kelas Cat akan memiliki kedua metode statis (maksud saya metode statis kelas Anak dan metode statis kelas Parent) Tapi bagaimana JVM menyembunyikan metode Parent Parent? Bagaimana cara menangani Heap dan Stack?


Ini bukanlah jawaban. Ini perpanjangan dari pertanyaan yang diajukan. Ini mungkin pertanyaan tersendiri atau bagian dari komentar pada pertanyaan.
Sri9911
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.