Javaで仮想関数/メソッドを書くことができますか?


165

C ++で行うように、Javaで仮想メソッドを作成することは可能ですか?

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

回答:


305

ウィキペディアから

ではJavaの、すべての非静的メソッドは、デフォルトである「仮想関数。」でマークされたメソッドのみ、最終的なキーワードと一緒に、上書きすることができない、 プライベートメソッド継承されていない、ある非仮想


3
これJon Skeetの答えの1つです。
Quazi Irfan、

それは本当だ場合、私は、動的メソッドディスパッチが唯一の方法は、上で呼び出されたオブジェクトのために起こる、Javaで、理由は私が読んだもののために、wonded -などについて説明し、ここで C ++のための仮想関数を説明する例ので 、ここでは、 Javaのための有効ではありません。
ブロッコリー

@QuaziIrfan JavaとC#の違いです。
Sreekanth Karumanaghat

101

Javaで仮想関数を記述できますか?

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

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

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

「通常の」仮想関数

次の例は、別の回答で言及されている古いバージョンのWikipediaページのものです。

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 インターフェースのメソッドはすべて仮想です。それら、メソッド実装を提供するために実装クラスに依存しているため、仮想である必要あります。実行するコードは実行時にのみ選択されます。

例えば:

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

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

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

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
これが最も完全な答えになるはずです。Javaにはキーワードがないため、仮想関数を実装する方法は2つあります。ありがとうございました。
クリストファーベールズ2014

ウィキペディアの引用よりもはるかに良い答え。c ++から来て、私のJavaの研究に怠惰な私は、abstractを探していました。
デビッド

@Davidこの答えはどうですか?ウィキペディアの引用は完全かつ簡潔で正確です。対照的に、この回答は部屋の象については言及していません。デフォルトでは、Javaのすべての関数(ウィキペディアの記事にリストされている例外を除く)は仮想です。仮想関数には抽象クラスもインターフェースも必要ないため、誤解を招くノイズが追加されるだけです。そして、これには「優れたコミュニケーションスキルと根本的な原則の深い習熟が必要」...ねえ。これは自己改ざんの発言です。貴重なディスク領域を無駄にしてしまう人はいませんでした。
ピーター-モニカ

ウィキペディアの投稿は、Javaだけでなく、あらゆる言語の仮想関数の概念に関するものであるため、この回答よりも劣っており、この回答に限定的ではありません。ウィキペディアのページにある例はCで書かれており、せいぜい不完全なものであり、誤解を招く可能性があります。すべての関数が仮想であり、仮想関数をノイズにするために抽象クラスまたはインターフェースを必要としないことの詳細。私はそれらが必要であると言ったことはありません、あなたはそれを誤解しました。最終的なポイントがわかりません。この質問が気に入らないので、削除してもよろしいですか?
Eric Leschinski、2015年

1
ここ数年遅れましたが素晴らしい答え
トムO.

55

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

「final」キーワードを追加して、非仮想関数を作成する必要はありません。

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


4
クラウスの回答で述べられているようなプライベート関数も非仮想です。
Don Larynx 2015年

9

すべての非プライベートインスタンスメソッドは、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は、Cと同じパッケージで、パブリック、保護、またはデフォルトアクセスで宣言されているか、または* m1は、m1とは異なるメソッドm3、m3をオーバーライドします。


1

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


「仮想変数」とはどういう意味ですか?
ネオエキスパート、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.