web-dev-qa-db-ja.com

仮想関数はC#とJavaでどのように機能しますか?

仮想関数はC#とJavaでどのように機能しますか?

C++と同様の同じvtableおよびvpointerの概念を使用していますか、それともまったく異なるものですか?

19
Naveen

仮想関数はJavaでどのように機能しますか?

コーディングインタビュアーはこの質問が大好きです。はい。 Javaには仮想キーワードがありませんが、Javaには仮想関数があり、それらを記述できます。

オブジェクト指向プログラミングでは、 仮想関数 または仮想メソッドは、継承クラス内で同じシグネチャを持つ関数によって動作をオーバーライドできる関数またはメソッドです。この概念は、オブジェクト指向プログラミング(OOP)のポリモーフィズム部分の非常に重要な部分です。

このような特定の言語についてアーキテクチャの質問をするためには、優れたコミュニケーションスキルと、Javaコンパイラ、特にインターフェイス、抽象クラス、および継承のしくみ)の基本原則を深く習得する必要があります。

インタビュアーを仮想関数の特定の例に導きます。

はい、仮想関数をJavaインターフェイス付きで記述できます。

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 implementing applyBrakes()
       System.out.println("Brakes applied"); //function, proving it is virtual.
    }
}

はい、仮想関数をJava抽象クラスで記述できます。

Java 抽象クラ​​ス 暗黙的に「仮想」メソッドが含まれ、それを拡張するクラスによって実装されます。例えば:

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 virtual function because it
}                                     //is part of an abstract class and isn't
                                      //final.  
class MyDog extends Dog{
    void jump(){
        System.out.println("boing");    //here jump() is being overridden, a 
    }                                   //demonstration that it is virtual.
}
public class Runner {
    public static void main(String[] args) {
        MyDog myDog = new MyDog();       //instantiating myDog
        myDog.jump();                    //calling the overridden function jump()
    }
}

関数をfinalにすることで、ジェネリッククラスで関数を仮想化しないように強制できます。

例えば:

class myJavaFoobarClass {

    final boolean giveMeTrueFunction()   //this Java function is NOT virtual
    {                                    //because final keyword prevents this
        return true;                     //function from being modified in a
    }                                    //subclass.

    boolean isItRainingFunction()   //this Java function IS virtual because
    {                               //without the final keyword, the function
        return false;               //can be overridden in a subclass.
    }
}
19
Eric Leschinski

少なくともJava)には仮想キーワードはありません。

呼び出しているメソッドの最も派生したバージョンに解決されるだけです...

class A{
void sayhi(){ System.out.println("A");}
}
class B extends A{
void sayhi(){ System.out.println("B");}
}

A a = new B();
a.sayhi();

「B」を印刷します。

クラスAbstractを宣言し、純粋仮想メソッドを宣言したが実装しないままにしておくことで、「純粋仮想」メソッドを作成できます。または、class/extendsの代わりにinterface/implementsを使用します。インターフェイスは基本的に、すべてのメソッドが純粋な仮想であるクラスです。これには、C++とは異なり、Javaクラスは他の1つのクラスしか直接継承できないため、クラスが複数のインターフェイスを実装できるという追加のボーナスがあります。

編集:


あなたのコメントに応えて、Naveen:

A a = new A();と言った場合a.sayhi(); 「A」と表示されます。

Javaの用語は動的です。仮想と考えることもできますが、一部のJava開発者。C++を知らない開発者は少なくとも。Javaには明示的なポインタがないため、仮想/非仮想について心配する必要はありません。VTableはありません。クラスとその祖先を見つけるまで、クラスとその祖先をバックトラックするだけです。必要なメソッドの実装。継承は1つしかないため、コンストラクターの順序について心配する必要はありません(常にボトムアップです)。

C++では、仮想メソッドがあり、次のようなことを行うと、異なる動作が発生します。

a->sayhi();

ここで、aはA *であり、代わりにBのインスタンスを指しています。

a.sayhi();

ここで、aはタイプBのオブジェクトを保持するタイプAのオブジェクトでした。

10
patros

Java仮想関数は完全に異なります。Javaでは、仮想関数はそのサブクラスでオーバーライドできる関数を意味します。したがって、Javaのすべての非静的メソッドは仮想関数です。final関数とprivate関数のみが継承されないため、仮想関数ではありません。

したがって、finalおよびprivateではないすべての非静的関数はJavaの仮想関数であると言えます。

4
Anshul Shukla

ポリモーフィズムをサポートするすべての言語は、vtablesを使用して、正しい関数へのメソッド呼び出しを解決します。したがって、Javaおよび.NET。

どちらも中間言語(.NETの場合はIL、Javaの場合はバイトコード)にコンパイルされますが、vtableはこの中間言語では表示されません。基盤となるエンジン(CLR for .NET)でサポートされています

2
Koen

Javaはバイナリ互換性をサポートできるため、vtablesを使用しないと確信しています。

明確にするために:vtableは、派生/サブクラスがコンパイルされるときに構築されます。ベース/スーパークラスのレイアウトが変更された場合は、d/sのvtableを再コンパイルする必要があります。 Javaでは、これは当てはまりません。d/ sを再コンパイルせずにb/sを変更できます。

うーん。実行時にvtableが構築される可能性があります。クラスがロードされたとき。この場合、JavaとC++は同じですが、異なります。

0