Java の仮想関数
このチュートリアルでは、Java での仮想関数/メソッドとは何か、および Java で仮想関数を使用する方法を紹介します。
基本クラスで定義され、派生クラスでオーバーライドできる関数は、仮想関数と呼ばれます。仮想関数の概念は、デフォルトで C++ と Java で使用されていました。非プライベートメソッドと非ファイナルメソッドはすべて仮想メソッドです。
C++ では、仮想キーワードを使用して仮想関数を作成しますが、Java にはそのようなキーワードはありません。そしてそれに加えて、すべての非プライベートメソッドと非ファイナルメソッドは仮想です。
仮想関数の概念は、オブジェクト指向プログラミングの概念とポリモーフィズムの観点から役立ちます。いくつかの例で理解しましょう。
Java の仮想関数
この例では、仮想の eat()
メソッドを含むクラス Human
を作成しました。これは仮想メソッドであるため、以下の例で行ったように、派生/子クラスでオーバーライドできます。どちらのメソッドも同じシグネチャを持ち、関数を呼び出すと、子クラスのメソッドのみが実行されます。以下の例を参照してください。
class Human {
void eat(String choice) {
System.out.println("I would like to eat - " + choice + " now");
}
}
public class SimpleTesting extends Human {
void eat(String choice) {
System.out.println("I would like to eat - " + choice);
}
public static void main(String[] args) {
SimpleTesting simpleTesting = new SimpleTesting();
simpleTesting.eat("Pizza");
simpleTesting.eat("Chicken");
}
}
出力:
I would like to eat - Pizza
I would like to eat - Chicken
JavaBean の仮想関数
Bean / POJO クラスのゲッター関数も仮想であり、子クラスによってオーバーライドできます。以下の例を参照してください。
public class SimpleTesting extends Student {
public int getId() {
System.out.println("Id : " + id);
return id;
}
public String getName() {
System.out.println("Name : " + name);
return name;
}
public int getAge() {
System.out.println("Age : " + age);
return age;
}
public static void main(String[] args) {
SimpleTesting student = new SimpleTesting();
student.setId(101);
student.setName("Rohan");
student.setAge(50);
student.getId();
student.getName();
student.getAge();
}
}
class Student {
int id;
String name;
int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
出力:
Id : 101
Name : Rohan
Age : 50
Java の非仮想関数
プライベートまたは final の関数は非仮想であるため、子クラスでオーバーライドすることはできません。この例では、2つの関数を作成しました。1つは final で、もう 1つは private です。これらを子クラスにオーバーライドしようとしましたが、非仮想関数が原因で Java コンパイラでエラーが発生しました。以下の例と出力を参照してください。
class Human {
// non-virtual method
final void eat(String choice) {
System.out.println("I would like to eat - " + choice);
}
// non-virtual method
private void buy(String item) {
System.out.println("Buy me a " + item);
}
}
public class SimpleTesting extends Human {
// non-virtual method
void eat(String choice) {
System.out.println("I would like to eat - " + choice);
}
// non-virtual method
void buy(String item) {
System.out.println("Buy me a " + item);
}
public static void main(String[] args) {
SimpleTesting simpleTesting = new SimpleTesting();
simpleTesting.eat("Pizza");
simpleTesting.buy("Pizza");
simpleTesting.eat("Chicken");
simpleTesting.buy("Chicken");
}
}
出力:
java.lang.IncompatibleClassChangeError: class SimpleTesting overrides final method Human.eat(Ljava/lang/String;)
---Cannot override the final method from Human---
Java インターフェイスの仮想関数
インターフェイスの関数/メソッドは、デフォルトでパブリックであり、子クラスによってオーバーライドされることになっているため、デフォルトでは仮想です。以下の例では、インターフェイスでメソッドを作成し、クラスでオーバーライドして、正常に呼び出しました。以下の例を参照してください。
interface Eatable {
void eat(String choice);
}
public class SimpleTesting implements Eatable {
public void eat(String choice) {
System.out.println("I would like to eat - " + choice);
}
void buy(String item) {
System.out.println("Buy me a " + item);
}
public static void main(String[] args) {
SimpleTesting simpleTesting = new SimpleTesting();
simpleTesting.eat("Pizza");
simpleTesting.buy("Pizza");
simpleTesting.eat("Chicken");
simpleTesting.buy("Chicken");
}
}
出力:
I would like to eat - Pizza
Buy me a Pizza
I would like to eat - Chicken
Buy me a Chicken