Bisakah Anda menulis fungsi / metode virtual di Jawa?


165

Apakah mungkin untuk menulis metode virtual di Jawa, seperti yang akan dilakukan di C ++?

Atau, apakah ada pendekatan Java yang tepat yang dapat Anda terapkan yang menghasilkan perilaku serupa? Bisakah saya punya beberapa contoh?

Jawaban:


305

Dari wikipedia

Di Jawa , semua metode non-statis secara default " fungsi virtual. " Hanya metode yang ditandai dengan kata kunci akhir , yang tidak dapat diganti, bersama dengan metode pribadi , yang tidak diwariskan, adalah non-virtual .


3
Inilah salah satu jawaban Jon Skeet .
Quazi Irfan

Saya bertanya-tanya apakah itu benar, karena untuk apa yang saya baca, di Jawa, pengiriman metode dinamis hanya terjadi pada objek metode yang dipanggil - seperti yang dijelaskan di sini sehingga contoh yang menjelaskan fungsi virtual untuk C ++ di sini tidak berlaku untuk java.
Brokoli

@QuaziIrfan Itulah perbedaan antara Java dan C #.
Sreekanth Karumanaghat

101

Bisakah Anda menulis fungsi virtual di Java?

Iya. Faktanya, semua metode instance di Java adalah virtual secara default. Hanya metode tertentu yang tidak virtual:

  • Metode kelas (karena biasanya setiap instance menyimpan informasi seperti pointer ke vtable tentang metode spesifiknya, tetapi tidak ada instance yang tersedia di sini).
  • Metode instance privat (karena tidak ada kelas lain yang dapat mengakses metode, instance panggilan selalu tipe kelas mendefinisikan itu sendiri dan oleh karena itu diketahui secara pasti pada waktu kompilasi).

Berikut ini beberapa contohnya:

Fungsi virtual "Normal"

Contoh berikut adalah dari versi lama halaman wikipedia yang disebutkan dalam jawaban lain.

import java.util.*;

public class Animal 
{
   public void eat() 
   { 
      System.out.println("I eat like a generic Animal."); 
   }

   public static void main(String[] args) 
   {
      List<Animal> animals = new LinkedList<Animal>();

      animals.add(new Animal());
      animals.add(new Fish());
      animals.add(new Goldfish());
      animals.add(new OtherAnimal());

      for (Animal currentAnimal : animals) 
      {
         currentAnimal.eat();
      }
   }
}

class Fish extends Animal 
{
   @Override
   public void eat() 
   { 
      System.out.println("I eat like a fish!"); 
   }
}

class Goldfish extends Fish 
{
   @Override
   public void eat() 
   { 
      System.out.println("I eat like a goldfish!"); 
   }
}

class OtherAnimal extends Animal {}

Keluaran:

Saya makan seperti Hewan generik.
Saya makan seperti ikan!
Saya makan seperti ikan mas!
Saya makan seperti Hewan generik.

Contoh dengan fungsi virtual dengan antarmuka

Metode antarmuka Java semuanya virtual. Mereka harus virtual karena mereka bergantung pada kelas implementasi untuk menyediakan implementasi metode. Kode yang akan dieksekusi hanya akan dipilih pada saat run time.

Sebagai contoh:

interface Bicycle {         //the function applyBrakes() is virtual because
    void applyBrakes();     //functions in interfaces are designed to be 
}                           //overridden.

class ACMEBicycle implements Bicycle {
    public void applyBrakes(){               //Here we implement applyBrakes()
       System.out.println("Brakes applied"); //function
    }
}

Contoh dengan fungsi virtual dengan kelas abstrak.

Mirip dengan antarmuka Kelas abstrak harus berisi metode virtual karena mereka bergantung pada implementasi perluasan kelas. Sebagai contoh:

abstract class Dog {                   
    final void bark() {               //bark() is not virtual because it is 
        System.out.println("woof");   //final and if you tried to override it
    }                                 //you would get a compile time error.

    abstract void jump();             //jump() is a "pure" virtual function 
}                                     
class MyDog extends Dog{
    void jump(){
        System.out.println("boing");    //here jump() is being overridden
    }                                  
}
public class Runner {
    public static void main(String[] args) {
        Dog dog = new MyDog();       // Create a MyDog and assign to plain Dog variable
        dog.jump();                  // calling the virtual function.
                                     // MyDog.jump() will be executed 
                                     // although the variable is just a plain Dog.
    }
}

1
Ini harus menjadi jawaban yang paling lengkap. Ini menyediakan 2 cara untuk mengimplementasikan fungsi virtual karena java tidak memiliki kata kunci. Terima kasih.
Christopher Bales

Jawabannya jauh lebih baik daripada kutipan Wikipedia. Berasal dari c ++ dan malas dengan studi Java saya, abstrak adalah apa yang saya cari.
David

@ David Bagaimana jawaban ini lebih baik? Kutipan wikipedia lengkap, singkat dan benar. Sebaliknya, jawaban ini gagal menyebut gajah di dalam ruangan: Secara default semua fungsi di Jawa (dengan pengecualian yang tercantum dalam artikel wikipedia) adalah virtual. Baik kelas abstrak maupun antarmuka tidak diperlukan untuk fungsi virtual, jadi itu hanya menambah noise yang menyesatkan. Dan kemudian ini "membutuhkan keterampilan komunikasi yang hebat dan penguasaan yang mendalam akan prinsip-prinsip dasar" ... ya ampun. Itu adalah pernyataan pemalsuan diri di sana: Tidak ada orang yang memiliki itu akan membuang ruang disk berharga dengannya.
Peter - Reinstate Monica

Posting wikipedia lebih rendah dan kurang spesifik untuk jawaban ini karena ini tentang konsep fungsi virtual dalam bahasa apa pun, bukan hanya java. Contoh yang diberikan di halaman wikipedia ditulis dalam bahasa C, dan ini adalah yang paling tidak lengkap, dan lebih menyesatkan. Detail tentang semua fungsi menjadi virtual, dan Anda tidak perlu kelas atau antarmuka abstrak untuk memiliki fungsi virtual sebagai derau. Saya tidak pernah mengatakan mereka diharuskan, Anda salah membaca itu. Saya tidak mengerti poin terakhir Anda, apakah Anda ingin saya menghapus pertanyaan ini karena Anda tidak menyukainya?
Eric Leschinski

1
Beberapa tahun terlambat di sini tetapi jawaban yang fantastis
Tom O.

55

Semua fungsi di Java adalah virtual secara default.

Anda harus keluar dari cara Anda untuk menulis fungsi non-virtual dengan menambahkan kata kunci "final".

Ini kebalikan dari standar C ++ / C #. Fungsi kelas adalah non-virtual secara default; Anda membuatnya dengan menambahkan pengubah "virtual".


4
fungsi pribadi sebagaimana dinyatakan dalam jawaban Klaus juga non-virtual.
Don Larynx

9

Semua metode instance non-pribadi adalah virtual secara default di Jawa.

Dalam C ++, metode pribadi bisa virtual. Ini dapat dieksploitasi untuk idiom non-virtual-interface (NVI). Di Jawa, Anda harus membuat metode NVI yang dapat ditimpa dilindungi.

Dari Spesifikasi Bahasa Jawa, v3:

8.4.8.1 Overriding (dengan Metode Instance) Suatu metode instance m1 yang dideklarasikan dalam kelas C menimpa metode instance lain, m2, dideklarasikan di kelas A jika semua hal berikut ini benar:

  1. C adalah subkelas dari A.
  2. Tanda tangan m1 adalah subsignature (§8.4.2) dari tanda tangan m2.
  3. Entah * m2 bersifat publik, dilindungi atau dideklarasikan dengan akses default dalam paket yang sama dengan C, atau * m1 mengganti metode m3, m3 berbeda dari m1, m3 berbeda dari m2, sehingga m3 menimpa m2.


1

Di Java, semua variabel & fungsi publik (non-pribadi) adalah Virtual secara default. Selain itu variabel & fungsi yang menggunakan kata kunci akhir tidak virtual .


apa yang Anda maksud dengan "variabel virtual"?
neoexpert
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.