抽象関数と仮想関数の違いは何ですか?


1578

抽象関数と仮想関数の違いは何ですか?仮想または抽象の使用が推奨されるのはどの場合ですか?どちらが最善のアプローチですか?


271
抽象関数はオーバーライドする必要がありますが、仮想関数はオーバーライドできます。
ジョーダンパーマー

15
仮想関数は、基本クラスにデフォルトの/ generic実装を持つことができます。
Martin

5
ここでのキーワードは抽象的です。それらは存在せず、関数が何であるかについての漠然とした考えです(メソッドシグネチャ)
Cole Johnson

回答:


2733

抽象関数は機能を持つことができません。基本的に言って、すべての子クラスはこのメソッドの独自のバージョンを提供する必要がありますが、親クラスで実装しようとすることさえ一般的です。

仮想関数は、基本的には見た目ですが、ここでは子クラスにとって十分かそうでない機能があります。それで十分であれば、このメソッドを使用し、そうでなければ、私をオーバーライドして、独自の機能を提供します。


396
そしてもちろん、仮想メソッドをオーバーライドする場合、base.Foo(...)を呼び出すことで常に親メソッドを参照できます
Brann

196
ありがとう。これは、MSDNドキュメントのどの説明よりもはるかに優れた簡単な説明です(これを読んで5分後に頭痛がしました:msdn.microsoft.com/en-us/library/aa645767(v=vs.71 ) .aspx
ジェイク

15
Javaから来て、これを読むまで、なぜそれを仮想化する必要があるのか​​少し戸惑いました:stackoverflow.com/a/1062126/193634
Rosdi Kasim

4
@MeqDotNetそれは私の実装が好きなら、私よりも自分のものを書いていないのなら私を使ってください:)
Usman Younas

16
これは、私が10分間読んで混乱したMicrosoftリファレンスライブラリにあるはずです。
SamChen 2014年

303

抽象関数は実装されておらず、抽象クラスでのみ宣言できます。これにより、派生クラスは強制的に実装を提供します。

仮想関数はデフォルトの実装を提供し、抽象クラスまたは非抽象クラスのいずれかに存在できます。

だから例えば:

public abstract class myBase
{
    //If you derive from this class you must implement this method. notice we have no method body here either
    public abstract void YouMustImplement();

    //If you derive from this class you can change the behavior but are not required to
    public virtual void YouCanOverride()
    { 
    }
}

public class MyBase
{
   //This will not compile because you cannot have an abstract method in a non-abstract class
    public abstract void YouMustImplement();
}

28
サンプルコードを見るのに非常に便利です-回答のさまざまな説明をより明確にするのに役立ちます
Simon Tewsi 2013年

2
前のバージョンへの回答をロールバックしました。2つのクラスは単なる例であり、最初のクラスは抽象としてマークされているためコンパイルされ、2番目のクラスはコンパイルされません。MyBaseが他のクラスから継承するかどうかは関係ありません。
Dirk

2
どういうわけか、あなたのMyBaseクラスは抽象クラスを実装する必要はありませんか?私はこれを頻繁にしないので、私は誤解される可能性があります。あなたの例ではそれはわかりません。
jp2code 2014年

2
上記の例では、MyBaseは実行できないことを示しています。つまり、非抽象クラスに抽象メソッドを
含める

80
  1. メンバーabstractを持つことができるのはクラスだけabstractです。
  2. abstract継承するクラスabstractのクラスがなければならない overrideそのabstractメンバー。
  3. abstractメンバーは、暗黙的ですvirtual
  4. abstractメンバーは、(任意の実装を提供することはできませんabstractと呼ばれているpure virtualいくつかの言語で)。

3番は私には意味がありません。「抽象クラスのメンバーは暗黙的に仮想である」と言うつもりだったと思います(つまり、仮想クラスであることを指定しなくても、その機能を提供できます)。
Hobo Spider

5
いいえ、私が書いたものを正確に意味しました。抽象クラスのメンバーは、でもそうでなくてvirtualもかまいませんvirtualabstractメンバー(すなわち抽象的性質、抽象メソッドは)つまりは、あなたがそれ自体で、デフォルトの実装を有していないことを除いて、それを上書きすることができ、単に仮想メソッドのようなものです。
Mehrdad Afshari、2014年

引用された「抽象的なメンバーは「暗黙的に」仮想です。」しかし、どこかで誰かが「仮想」キーワードを明示的に追加して抽象メンバーを作成したのを見ました。私はあなたの答えを読むまで、それは必要ではなく、実際、それは私に疑いを与えました。
bonCodigo 2014年

ポイント4のサポート参照を含めてください。そして、あなたの投稿は以前のものがまだ持っていなかった他のものをもたらしません。
ラファエル

これは説明のない一連のステートメントにすぎません。
リバースエンジニアリング

61

常に抽象関数をオーバーライドする必要があります。

したがって:

  • 抽象関数 - 継承者が独自の実装を提供する必要がある場合
  • 仮想 - 決定するのは継承者次第

37

抽象関数:

  1. 抽象クラス内でのみ宣言できます。
  2. 抽象クラスの実装ではなく、メソッド宣言のみが含まれています。
  3. 派生クラスでオーバーライドする必要があります。

仮想機能:

  1. 抽象クラスと非抽象クラスの内部で宣言できます。
  2. メソッドの実装が含まれています。
  3. 上書きされる可能性があります。

29

抽象メソッド:クラスに抽象メソッドが含まれている場合、そのクラスは抽象として宣言する必要があります。抽象メソッドには実装がないため、その抽象クラスから派生するクラスは、この抽象メソッドの実装を提供する必要があります。

仮想メソッド:クラスは仮想メソッドを持つことができます。仮想メソッドには実装があります。仮想メソッドを持つクラスから継承する場合、仮想メソッドオーバーライドして追加のロジックを提供するか、ロジックを独自の実装に置き換えることができます。

何を使用するか:場合によっては、特定の型に特定のメソッドが必要であることがわかっていますが、このメソッドがどのような実装を持つ必要があるかはわかりません。
このような場合、このシグネチャを持つメソッドを含むインターフェースを作成できます。ただし、そのようなケースがあり、そのインターフェースのインプリメンターが別の一般的なメソッド(すでに実装を提供できる)も持っていることがわかっている場合は、抽象クラスを作成できます。この抽象クラスには、抽象メソッド(オーバーライドする必要があります)と、「共通」ロジックを含む別のメソッドが含まれます。

必須ではありませんが、直接使用できるが、継承者が特定の動作を変更できるようにするクラスがある場合は、仮想メソッドを使用する必要があります。


29

説明:類推あり。うまくいけば、それはあなたを助けるでしょう。

環境

私は建物の21階で働いています。そして、私は火について妄想的です。時々、世界のどこかで、火が空のスクレーパーを燃やしています。しかし、幸運なことに、火災が発生した場合の対処方法については、次の場所に取扱説明書があります。

FireEscape()

  1. 持ち物を収集しない
  2. ファイアエスケープまで歩く
  3. 建物から出る

これは基本的にはFireEscape()と呼ばれる仮想メソッドです

仮想メソッド

この計画は、99%の状況に非常に適しています。それが機能する基本的な計画です。しかし、1%の確率でファイアエスケープがブロックまたは損傷します。この場合、完全にねじ込まれ、思い切った操作を行わないとトーストになります。仮想メソッドを使用すると、それを行うことができます。基本的なFireEscape()プランを独自のバージョンのプランでオーバーライドできます。

  1. ウィンドウまで実行
  2. 窓から飛び出す
  3. 安全に下にパラシュート

言い換えると、仮想メソッドは基本的な計画を提供し、必要に応じてオーバーライドできます。プログラマーが適切と判断した場合、サブクラスは親クラスの仮想メソッドをオーバーライドできます。

抽象メソッド

すべての組織が十分に訓練されているわけではありません。消防訓練を行わない組織もあります。彼らは全体的な脱出ポリシーを持っていません。すべての人は自分のためです。経営者は、そのような既存の方針にのみ関心があります。

言い換えれば、それぞれの人がされて強制的に彼自身のFireEscape()メソッドを開発します。1人の男がファイアエスケープを歩きます。別の男がパラシュートします。別の男は、ロケット推進技術を使用して建物から離れて飛びます。別の男がアブセイルします。基本的なFireEscape()計画がある限り、経営者はどのように脱出するを気にしません-もしそうでなければ、OHSが大量のレンガのように組織に降りてくることが保証されます。これは、抽象メソッドが意味するものです。

2つの違いは何ですか?

抽象メソッド:サブクラスがされて強制的に自分のFireEscapeメソッドを実装します。仮想メソッドを使用すると、あなたはあなたを待っている基本的な計画を持っていますが、それが十分でない場合は独自の計画を実装することを選択できます。

今はそれほど難しくありませんでしたか?


22

抽象メソッドは、具象クラスを作成するために実装する必要があるメソッドです。宣言は抽象クラスにあり(抽象メソッドを持つクラスは抽象クラスでなければなりません)、具象クラスに実装する必要があります。

仮想メソッドは、オーバーライドを使用して派生クラスでオーバーライドでき、スーパークラスの動作を置き換えることができるメソッドです。オーバーライドしないと、元の動作が得られます。そうすると、常に新しい動作が得られます。これは、オーバーライドできないが元のメソッドを隠すことができる仮想メソッドではないことに反対しています。これはnew修飾子を使用して行われます。

次の例を参照してください。

public class BaseClass
{
    public void SayHello()
    {
        Console.WriteLine("Hello");
    }


    public virtual void SayGoodbye()
    {
        Console.WriteLine("Goodbye");
    }

    public void HelloGoodbye()
    {
        this.SayHello();
        this.SayGoodbye();
    }
}


public class DerivedClass : BaseClass
{
    public new void SayHello()
    {
        Console.WriteLine("Hi There");
    }


    public override void SayGoodbye()
    {
        Console.WriteLine("See you later");
    }
}

インスタンス化DerivedClassしてSayHello、またはを呼び出すと、SayGoodbye「こんにちは」と「後でお会いしましょう」というメッセージが表示されます。に電話するとHelloGoodbye、「こんにちは」と「またお会いしましょう」というメッセージが表示されます。これはSayGoodbyeが仮想であり、派生クラスに置き換えることができるためです。SayHelloは非表示になっているだけなので、基本クラスから呼び出すと、元のメソッドが取得されます。

抽象メソッドは暗黙的に仮想です。これらは、インターフェースのように、存在しなければならない動作を定義します。


9

抽象メソッドは常に仮想です。実装することはできません。

それが主な違いです。

基本的に、「デフォルト」の実装があり、子孫がその動作を変更できるようにする場合は、仮想メソッドを使用します。

抽象メソッドでは、子孫に実装を提供するように強制します。


9

(他の回答から)次のクラスにいくつかの改善を加えることで、これをより簡単にしました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestOO
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass _base = new BaseClass();
            Console.WriteLine("Calling virtual method directly");
            _base.SayHello();
            Console.WriteLine("Calling single method directly");
            _base.SayGoodbye();

            DerivedClass _derived = new DerivedClass();
            Console.WriteLine("Calling new method from derived class");
            _derived.SayHello();
            Console.WriteLine("Calling overrided method from derived class");
            _derived.SayGoodbye();

            DerivedClass2 _derived2 = new DerivedClass2();
            Console.WriteLine("Calling new method from derived2 class");
            _derived2.SayHello();
            Console.WriteLine("Calling overrided method from derived2 class");
            _derived2.SayGoodbye();
            Console.ReadLine();
        }
    }


    public class BaseClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }
        public virtual void SayGoodbye()
        {
            Console.WriteLine("Goodbye\n");
        }

        public void HelloGoodbye()
        {
            this.SayHello();
            this.SayGoodbye();
        }
    }


    public abstract class AbstractClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }


        //public virtual void SayGoodbye()
        //{
        //    Console.WriteLine("Goodbye\n");
        //}
        public abstract void SayGoodbye();
    }


    public class DerivedClass : BaseClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }

        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }

    public class DerivedClass2 : AbstractClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }
        // We should use the override keyword with abstract types
        //public new void SayGoodbye()
        //{
        //    Console.WriteLine("See you later2");
        //}
        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }
}

6

バインディングは、名前をコードのユニットにマッピングするプロセスです。

レイトバインディングとは、名前を使用するがマッピングは延期することを意味します。言い換えると、最初に名前を作成/メンションし、その後のいくつかのプロセスにその名前へのコードのマッピングを処理させます。

今検討してください:

  • 人間と比較して、機械は検索と並べ替えに本当に優れています
  • 機械と比較して、人間は本当に発明と革新が得意です

つまり、短い答えはvirtual、マシン(実行時)abstractに対する遅延バインディングの指示であるのに対して、人間(プログラマ)に対する遅延バインディングの指示です。

つまり、次のvirtualことを意味します。

「親愛なるランタイム、あなたが最善を尽くすことを行うことによって適切なコードをこの名前にバインドします:検索

abstract意味:

「親愛なるプログラマー、あなたが最善を尽くすことを行うことによってこの名前に適切なコードをバインドしてください:発明

完全を期すために、オーバーロードとは次のことを意味します。

「親愛なるコンパイラ、あなたが最善を尽くすことを行うことによって適切なコードをこの名前にバインドします:ソート」。


3

継承者が必要に応じて機能を拡張する場合は、基本的に仮想メソッドを使用します。

継承者に機能を実装させたい場合は抽象メソッドを使用します(この場合、それらには選択の余地がありません)。


3

仮想メソッド

  • 仮想とは、それを上書きできることを意味します。

  • 仮想機能には実装があります。クラスを継承すると、仮想関数をオーバーライドして独自のロジックを提供できます。


  • 子クラスに関数を実装するときに、仮想関数の戻り値の型を変更できます(
    シャドウイングの概念とも言えます)。

抽象メソッド

  • 抽象とは、オーバーライドする必要があることを意味します。

  • 抽象関数には実装がなく、抽象クラスになければなりません。

  • 宣言のみ可能です。これにより、派生クラスはその実装を提供します。

  • 抽象メンバーは暗黙的に仮想です。一部の言語では、アブストラクトを純粋仮想として呼び出すことができます。

    public abstract class BaseClass
    { 
        protected abstract void xAbstractMethod();
    
        public virtual void xVirtualMethod()
        {
            var x = 3 + 4;
        }
    } 
    

2

いくつかの場所で、抽象メソッドが以下のように定義されているのを見てきました。**

「抽象メソッドは子クラスに実装する必要があります」

**のように感じました。

子クラスも抽象である場合、抽象メソッドを子クラスに実装する必要はありません。

1)抽象メソッドは、カントのプライベートメソッドです。2)抽象メソッドを傾ける同じ抽象クラスで実装されてもよいです。

抽象クラスを実装している場合は、基本抽象クラスの抽象メソッドをオーバーライドする必要があります。なぜなら、抽象メソッドの実装はオーバーライドキーワードを使用するためです。仮想メソッドと同様です。

継承されたクラスに仮想メソッドを実装する必要はありません。

                                 ----------CODE--------------

public abstract class BaseClass
{
    public int MyProperty { get; set; }
    protected abstract void MyAbstractMethod();

    public virtual void MyVirtualMethod()
    {
        var x = 3 + 4;
    }

}
public abstract class myClassA : BaseClass
{
    public int MyProperty { get; set; }
    //not necessary to implement an abstract method if the child class is also abstract.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}
public class myClassB : BaseClass
{
    public int MyProperty { get; set; }
    //You must have to implement the abstract method since this class is not an abstract class.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}

2

上記の例のほとんどはコードを使用しており、非常に優れています。私は彼らが言うことを追加する必要はありませんが、以下はコード/技術用語ではなくアナロジーを利用する簡単な説明です。

簡単な説明-類推による説明

抽象メソッド

ジョージWブッシュだと思う。彼は兵士に「イラクで戦おう」と言います。以上です。彼が指定したすべては、戦いが行われなければならないということです。彼はそれがどのように起こる正確には明記していない。しかし、つまり、外に出て「戦う」ことはできません。それは、正確にはどういう意味ですか?B-52またはデリンジャーと戦うのですか?これらの具体的な詳細は他の誰かに任されています。これは抽象メソッドです。

仮想メソッド

David Petraeusは軍の上位にいます。彼は戦いの意味を定義しました:

  1. 敵を見つける
  2. 彼を無力化してください。
  3. その後ビールを飲む

問題は、それが非常に一般的な方法であることです。これは機能する優れた方法ですが、十分に具体的でない場合もあります。ペトラエウスにとって良いことは、彼の命令には余裕と範囲があることです-彼は他の人が彼らの特定の要件に従って彼の「戦い」の定義を変更することを許可しました。

Private Job Bloggsはペトラエウスの命令を読み、彼の特定の要件に従って、彼自身のバージョンの戦いを実装する許可を与えられています。

  1. 敵を見つけてください。
  2. 彼の頭を撃ちなさい。
  3. 家に帰る
  4. ビールを飲みます。

ヌーリアルマリキもペトラエウスから同じ注文を受けました。彼はまた戦うことです。しかし、彼は政治家であり、歩兵ではありません。明らかに彼は政治家の敵を頭の中で撃ち回ることはできません。ペトレウスは彼に仮想メソッドを与えたので、マリキは彼の特定の状況に従って、彼自身のバージョンのfightメソッドを実装することができます:

  1. 敵を見つけてください。
  2. 彼はいくつかのBSが起訴された罪で逮捕されました。
  3. 家に帰る
  4. ビールを飲みます。

言い換えると、仮想メソッドは定型的な指示を提供しますが、これらは一般的な指示であり、特定の状況に応じて、軍の階層の下の人々がより具体的にすることができます。

2つの違い

  • George Bushは実装の詳細を証明していません。これは他の誰かが提供する必要があります。これは抽象メソッドです。

  • 一方、Petraeus 実装の詳細を提供しますが、部下がより良い何かを思い付くことができる場合は、自分の注文を自分のバージョンで上書きすることを部下に許可しました。

お役に立てば幸いです。


2

抽象関数(メソッド):

●抽象メソッドは、キーワードabstractで宣言されるメソッドです。

●本体はありません。

●派生クラスで実装する必要があります。

●メソッドが抽象の場合、クラスは抽象化する必要があります。

仮想関数(メソッド):

●仮想メソッドは、virtualキーワードで宣言されたメソッドであり、overrideキーワードを使用して派生クラスメソッドによってオーバーライドできます。

●オーバーライドするかどうかは、派生クラス次第です。


1

答えは何度も提供されていますが、それぞれをいつ使用するかという問題は設計時の決定です。一般的なメソッド定義を個別のインターフェースにバンドルし、適切な抽象化レベルでそれらをクラスにプルすることを試みるのは良い習慣だと思います。抽象メソッドと仮想メソッドの定義の共通セットをクラスにダンプすると、簡潔なインターフェイスのセットを実装する非抽象クラスを定義するのが最善の場合に、クラスがインスタンス化できなくなります。いつものように、それはあなたのアプリケーション固有のニーズに最適なものに依存します。


1

抽象関数は本体を持つことができず、子クラスによってオーバーライドされる必要があります

仮想関数には本体があり、子クラスによってオーバーライドされる場合とオーバーライドされない場合があります


1

一般的なオブジェクト指向の視点から:

抽象メソッドについて:親クラスに抽象メソッドを配置すると、実際には子クラスに対して次のように言われます。このようなメソッドシグネチャがあることに注意してください。そして、それを使用したい場合は、独自に実装する必要があります!

仮想関数について:親クラスに仮想メソッドを配置すると、派生クラスに対して次のように言うことになります:ここで、何かを行う機能があります。これが便利な場合は、そのまま使用してください。そうでない場合は、これをオーバーライドしてコードを実装してください。コードで私の実装を使用することもできます。

これは、一般的なオブジェクト指向のこの2つの概念の違いに関するいくつかの哲学です。


1

抽象関数は実装ではなく「単なる」シグネチャです。これは、クラスの使用方法を宣言するためにインターフェースで使用されます。派生クラスの1つに実装する必要があります。

仮想関数(実際にはメソッド)も宣言する関数であり、継承階層クラスの1つに実装する必要があります。

そのようなクラスの継承されたインスタンスは、下位階層クラスで実装しない限り、実装も継承します。


1

クラスがこの抽象クラスから派生した場合、抽象メンバーをオーバーライドする必要があります。これは、メンバーをオプションでオーバーライドできることを指定する仮想修飾子とは異なります。


0

C#には仮想クラスの呼び出しはありません。

機能について

  1. 抽象関数は署名のみを持ち、ドライブクラスは機能でオーバーライドする必要があります。
  2. 仮想機能は、ドライブクラスが要件に応じてオーバーライドする場合としない場合がある機能の一部を保持します

あなたはあなたの要件で決めることができます。


0

抽象メソッドには実装がなく、親クラスで宣言されています。子クラスは、そのメソッドを実装する責任があります。

仮想メソッドは、親クラスに実装を持つ必要があり、それにより、子クラスは、親クラスのその実装を使用するか、子クラスのそのメソッドにそれ自体の新しい実装を持つかを選択できるようになります。


0

C ++の背景から、C#virtualはC ++ virtualに対応し、C#抽象メソッドはC ++ pure virtual関数に対応します


0

抽象関数またはメソッドは、クラスによって公開されるパブリックな「操作の名前」であり、その目的は、抽象クラスとともに、オブジェクトが実装する必要のある構造に対するオブジェクト設計における制約の形式を主に提供します。

実際、その抽象クラスから継承するクラスは、このメソッドに実装を提供する必要があります。通常、コンパイラは、そうでない場合にエラーを発生させます。

抽象クラスとメソッドを使用することは、クラスを設計するときに実装の詳細に焦点を当てることにより、クラス構造が実装に関連しすぎて、依存関係を作成し、それらの間で協調するクラス間の結合を回避するために、主に重要です。

仮想関数または仮想メソッドは、単にクラスのパブリック動作をモデル化するメソッドですが、子クラスはその動作に特定の拡張機能を実装する必要があると考えられるため、継承チェーンでそれを自由に変更できます。

これらは両方とも、オブジェクト指向パラダイムにおける形の形式を表しています。

抽象メソッドと仮想関数を一緒に使用して、優れた継承モデルをサポートできます。

ソリューションの主要なオブジェクトの適切な抽象的な構造を設計し、さらに特殊化しやすいものを見つけて基本的な実装を作成し、これらを仮想化します。最後に、継承された仮想化を最終的に「オーバーライド」して基本的な実装を特殊化します。


0

ここでは、インターフェイス、抽象クラス、および通常のクラスの動作を非常に基本的なレベルで確認するための具体的な例になることを期待して、いくつかのサンプルコードを書いています。デモとして使用する場合は、このコードをプロジェクトとしてgithubで見つけることもできます。https//github.com/usavas/JavaAbstractAndInterfaceDemo

public interface ExampleInterface {

//    public void MethodBodyInInterfaceNotPossible(){
//    }
    void MethodInInterface();

}

public abstract class AbstractClass {
    public abstract void AbstractMethod();

    //    public abstract void AbstractMethodWithBodyNotPossible(){
    //
    //    };

    //Standard Method CAN be declared in AbstractClass
    public void StandardMethod(){
        System.out.println("Standard Method in AbstractClass (super) runs");
    }
}

public class ConcreteClass
    extends AbstractClass
    implements ExampleInterface{

    //Abstract Method HAS TO be IMPLEMENTED in child class. Implemented by ConcreteClass
    @Override
    public void AbstractMethod() {
        System.out.println("AbstractMethod overridden runs");
    }

    //Standard Method CAN be OVERRIDDEN.
    @Override
    public void StandardMethod() {
        super.StandardMethod();
        System.out.println("StandardMethod overridden in ConcreteClass runs");
    }

    public void ConcreteMethod(){
        System.out.println("Concrete method runs");
    }

    //A method in interface HAS TO be IMPLEMENTED in implementer class.
    @Override
    public void MethodInInterface() {
        System.out.println("MethodInInterface Implemented by ConcreteClass runs");

    //    Cannot declare abstract method in a concrete class
    //    public abstract void AbstractMethodDeclarationInConcreteClassNotPossible(){
    //
    //    }
    }
}

-4

私の理解に:

抽象メソッド:

抽象クラスのみが抽象メソッドを保持できます。また、派生クラスはメソッドを実装する必要があり、クラスで実装は提供されません。

仮想メソッド:

クラスはこれらを宣言し、同じものの実装を提供できます。また、派生クラスは、それをオーバーライドするメソッドを実装する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.