Java'da sanal işlevler / yöntemler yazabilir misiniz?


166

C ++ ile olduğu gibi Java'da sanal yöntemler yazmak mümkün mü ?

Veya, benzer davranışlar üreten, uygulayabileceğiniz uygun bir Java yaklaşımı var mı? Bazı örnekler alabilir miyim?

Yanıtlar:


306

Gönderen wikipedia

In Java , statik olmayan tüm yöntemler varsayılan olarak " sanal fonksiyonlar. " İle işaretlenmiş Sadece yöntemleri son anahtar kelime ile birlikte geçersiz kılınan olamaz, hangi özel yöntemlerle miras alınmaz, vardır olmayan sanal .


3
İşte biridir Jon Skeet 'ın cevabı.
Quazi Irfan

Bunun nedeni ne okudum, Java, dinamik yöntem sevk tek yöntem çağrıldığında nesnenin olur için, gerçekten doğruysa wonded - olarak açıklanabilir burada böylece örneğin C ++ için sanal fonksiyonlarını açıklayan burada java için geçerli değil.
Brokoli

@QuaziIrfan Java ve C # arasındaki fark bu.
Sreekanth Karumanaghat

101

Java'da sanal işlevler yazabilir misiniz?

Evet. Aslında, Java'daki tüm örnek yöntemleri varsayılan olarak sanaldır. Yalnızca belirli yöntemler sanal değildir:

  • Sınıf yöntemleri (çünkü tipik olarak her örnek, belirli yöntemleri hakkında bir vtable'a işaretçi gibi bilgi içerir, ancak burada örnek yoktur).
  • Özel örnek yöntemleri (başka hiçbir sınıf yönteme erişemediğinden, çağıran örnek her zaman tanımlayıcı sınıfın türüne sahiptir ve bu nedenle derleme zamanında açık bir şekilde bilinir).

İşte bazı örnekler:

"Normal" sanal işlevler

Aşağıdaki örnek, başka bir yanıtta belirtilen wikipedia sayfasının eski bir versiyonundan alınmıştır .

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 {}

Çıktı:

Ben jenerik bir Hayvan gibi yerim.
Balık gibi yerim!
Japon balığı gibi yerim!
Ben jenerik bir Hayvan gibi yerim.

Arayüzlü sanal işlevlere örnek

Java arayüz yöntemlerinin hepsi sanaldır. Onlar gerekir onlar yöntem uygulamaları sağlamak için uygulamaya sınıflar güvenmek çünkü sanal olun. Yürütülecek kod yalnızca çalışma zamanında seçilecektir.

Örneğin:

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
    }
}

Soyut sınıflı sanal fonksiyonlara örnek.

Arayüzleri benzer Özet sınıflar gerekir onlar uzanan sınıfların uygulanmasına bağlı olduğundan sanal yöntemleri içeriyor. Örneğin:

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
Bu en eksiksiz cevap olmalı. Java anahtar kelimesi olmadığından sanal bir işlevi uygulamak için 2 yol sağlar. Teşekkür ederim.
Christopher Bales

Wikipedia alıntısından çok daha iyi bir cevap. C ++ 'dan geliyor ve Java çalışmalarımla tembel olmak, aradığım şey buydu.
David

@David Bu cevap nasıl daha iyi? Wikipedia alıntısı tam, özlü ve doğrudur. Bu cevap, aksine, odadaki filden söz etmiyor: Varsayılan olarak Java'daki tüm işlevler (wikipedia makalesinde listelenen istisnalar hariç) sanaldır. Sanal işlevler için ne soyut sınıflar ne de arabirimler gerekli olduğundan, bu yalnızca yanıltıcı gürültü ekler. Ve sonra bu "büyük iletişim becerileri ve altta yatan ilkelere derin bir hakimiyet gerektirir" ... jeez. Bu kendi kendini sahtekâr bir ifadedir: Buna sahip olan hiç kimse onunla değerli disk alanını boşa harcamaz.
Peter - Monica'yı yeniden

Vikipedi postu daha düşüktür ve bu cevaba daha az özgüdür, çünkü sadece java yerine herhangi bir dilde sanal fonksiyon kavramı ile ilgilidir. Vikipedi sayfasında verilen örnek C ile yazılmıştır ve en iyi ihtimalle eksiktir ve daha yanıltıcıdır. Tüm işlevlerin sanal olduğu ve sanal işlevlerin parazit olması için soyut sınıflara veya arabirimlere ihtiyaç duymadığınız ayrıntı. Asla gerekli olduklarını söylemedim, yanlış anladın. Son noktanı anlamıyorum, beğenmediğin için bu soruyu silmemi ister misin?
Eric Leschinski

1
Birkaç yıl geç kaldı ama harika cevap
Tom O.

55

Java'daki tüm işlevler varsayılan olarak sanaldır.

"Son" anahtar kelimeyi ekleyerek sanal olmayan işlevler yazmak için kendi yolunuzdan çıkmanız gerekir.

Bu, C ++ / C # varsayılanının tam tersidir. Sınıf işlevleri varsayılan olarak sanal değildir; bunları "sanal" değiştirici ekleyerek yaparsınız.


4
Klaus'un cevabında belirtildiği gibi özel fonksiyonlar da sanal değildir.
Don Larynx

9

Özel olmayan tüm yönetim ortamı yöntemleri, Java'da varsayılan olarak sanaldır.

C ++ 'da özel yöntemler sanal olabilir. Bu sanal olmayan arayüz (NVI) deyimi için kullanılabilir. Java'da, NVI'nın geçersiz kılınabilir yöntemlerini korumanız gerekir.

Java Dil Spesifikasyonu'ndan v3:

8.4.8.1 Geçersiz Kılma (Örnek Yöntemlere Göre) C sınıfında bildirilen bir örnek yöntemi m1, aşağıdakilerin tümü doğruysa A sınıfında bildirilen başka bir örnek yöntemini (m2) geçersiz kılar:

  1. C, A'nın bir alt sınıfıdır.
  2. M1 imzası m2 imzasının bir alt imzasıdır (§8.4.2).
  3. * M2 herkese açıktır, korunur veya C ile aynı pakette varsayılan erişimle ilan edilir veya * m1, m3, m1'den farklı m3, m3'ten farklı m3 yöntemini geçersiz kılar, böylece m3 m2'yi geçersiz kılar.


1

Java da, tüm kamu (özel olmayan) değişkenler ve fonksiyonlar Sanal varsayılan olarak. Dahası, final anahtar sözcüğünü kullanan değişkenler ve işlevler sanal değildir .


"sanal değişkenler" ile ne demek istiyorsun?
neoexpert
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.