web-dev-qa-db-ja.com

Javaで仮想関数/メソッドを作成できますか?

C++で行うように、Javaでvirtualメソッドを記述できますか?

または、同様の動作を生成する適切なJavaアプローチを実装できますか?いくつか例を挙げてもらえますか?

144
yonatan

wikipedia から

Javaでは、すべての非静的メソッドはデフォルトで「仮想関数です。 "キーワードfinalでマークされたメソッドのみ、privateメソッドは継承されず、non-virtualです。

271

Javaで仮想関数を作成できますか?

はい。実際、Javaのすべてのインスタンスメソッドはデフォルトで仮想です。特定のメソッドのみが仮想ではありません:

  • クラスメソッド(通常、各インスタンスはその特定のメソッドに関するvtableへのポインターのような情報を保持しますが、ここではインスタンスは利用できません)。
  • プライベートインスタンスメソッド(他のクラスがメソッドにアクセスできないため、呼び出し元のインスタンスは常に定義クラス自体の型を持ち、したがってコンパイル時に明確に認識されます)。

ここではいくつかの例を示します。

「通常の」仮想関数

次の例は、別の回答で言及されているウィキペディアページの 古いバージョン からのものです。

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

出力:

私は一般的な動物のように食べます。
私は魚のように食べます!
私は金魚のように食べます!
私は一般的な動物のように食べます。

インターフェイスを使用した例

Java インターフェイスメソッド はすべて仮想です。それらはメソッド実装を提供するために実装クラスに依存しているため、mustでなければなりません。実行するコードは、実行時にのみ選択されます。

例えば:

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

抽象クラスを持つ仮想関数の例

インターフェイスと同様 抽象クラ​​スmustは、拡張クラスの実装に依存しているため、仮想メソッドを含む必要があります。例えば:

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.
    }
}
88
Eric Leschinski

Javaのすべての関数はデフォルトで仮想です。

「final」キーワードを追加して、非仮想関数を書くために邪魔をする必要があります。

これは、C++/C#のデフォルトの反対です。クラス関数はデフォルトでは非仮想です。 「virtual」修飾子を追加することにより、それらを作成します。

54
duffymo

すべての非プライベートインスタンスメソッドは、Javaではデフォルトで仮想です。

C++では、プライベートメソッドを仮想にすることができます。これは、非仮想インターフェイス(NVI)イディオムに悪用される可能性があります。 Javaでは、NVIオーバーライド可能メソッドを保護する必要があります。

Java言語仕様、v3から:

8.4.8.1オーバーライド(インスタンスメソッドによる)クラスCで宣言されたインスタンスメソッドm1は、次のすべてが真である場合、クラスAで宣言された別のインスタンスメソッドm2をオーバーライドします。

  1. CはAのサブクラスです。
  2. M1の署名は、m2の署名のサブ署名(§8.4.2)です。
  3. * m2はpublic、protected、またはCと同じパッケージのデフォルトアクセスで宣言されているか、* m1はm3とm2をオーバーライドするように、m1とは異なるm3、m3、m2とは異なるm3、m3をオーバーライドします。
9
Andy Thomas

はい、Javaで仮想「関数」を作成できます。

2
RepDetec

Javaでは、すべてのパブリック(非プライベート)変数と関数は、デフォルトで仮想です。さらに、キーワードfinalを使用する変数と関数はvirtualではありません。

0
Parvej Ahmed