C++で行うように、Javaでvirtualメソッドを記述できますか?
または、同様の動作を生成する適切なJavaアプローチを実装できますか?いくつか例を挙げてもらえますか?
Javaでは、すべての非静的メソッドはデフォルトで「仮想関数です。 "キーワードfinalでマークされたメソッドのみ、privateメソッドは継承されず、non-virtualです。
はい。実際、Javaのすべてのインスタンスメソッドはデフォルトで仮想です。特定のメソッドのみが仮想ではありません:
ここではいくつかの例を示します。
「通常の」仮想関数
次の例は、別の回答で言及されているウィキペディアページの 古いバージョン からのものです。
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.
}
}
Javaのすべての関数はデフォルトで仮想です。
「final」キーワードを追加して、非仮想関数を書くために邪魔をする必要があります。
これは、C++/C#のデフォルトの反対です。クラス関数はデフォルトでは非仮想です。 「virtual」修飾子を追加することにより、それらを作成します。
すべての非プライベートインスタンスメソッドは、Javaではデフォルトで仮想です。
C++では、プライベートメソッドを仮想にすることができます。これは、非仮想インターフェイス(NVI)イディオムに悪用される可能性があります。 Javaでは、NVIオーバーライド可能メソッドを保護する必要があります。
Java言語仕様、v3から:
8.4.8.1オーバーライド(インスタンスメソッドによる)クラスCで宣言されたインスタンスメソッドm1は、次のすべてが真である場合、クラスAで宣言された別のインスタンスメソッドm2をオーバーライドします。
- CはAのサブクラスです。
- M1の署名は、m2の署名のサブ署名(§8.4.2)です。
- * m2はpublic、protected、またはCと同じパッケージのデフォルトアクセスで宣言されているか、* m1はm3とm2をオーバーライドするように、m1とは異なるm3、m3、m2とは異なるm3、m3をオーバーライドします。
はい、Javaで仮想「関数」を作成できます。
Javaでは、すべてのパブリック(非プライベート)変数と関数は、デフォルトで仮想です。さらに、キーワードfinalを使用する変数と関数はvirtualではありません。