virtual,overideの意味がわかる例です。
今回はコンソール。
Baseというのが基本クラス。
Inheritが継承するクラス。
それぞれメソッドでWriteLineしてどのメソッドが呼ばれたかを表示します。
using System;
namespace OverrideTest
{
class Base
{
public virtual void Test1()
{
Console.WriteLine("BaseのTest1が呼ばれました");
}
public void Test2()
{
Console.WriteLine("BaseのTest2が呼ばれました");
}
}
class Inherit : Base
{
public override void Test1()
{
Console.WriteLine("InheritのTest1が呼ばれました");
}
public new void Test2()
{
Console.WriteLine("InheritのTest2が呼ばれました");
}
}
class Program
{
static void Main(string[] args)
{
Base Base = new Base();
Base.Test1();//BaseのTest1が呼ばれました
Base.Test2();//BaseのTest2が呼ばれました
Console.WriteLine();//見やすいように改行
Inherit Inherit = new Inherit();
Inherit.Test1();//InheritのTest1が呼ばれました
Inherit.Test2();//InheritのTest2が呼ばれました
Console.WriteLine();//見やすいように改行
Base Test = new Inherit();//継承元のクラスには、暗黙的に型変換できる
Test.Test1();//InheritのTest1が呼ばれました
Test.Test2();//BaseのTest2が呼ばれました
Console.WriteLine("Press any key to continue");
Console.ReadKey();
}
}
}
さて、少し詳しくmain処理を見ていきます。
Base Base = new Base();
Base.Test1();//BaseのTest1が呼ばれました
Base.Test2();//BaseのTest2が呼ばれました
Console.WriteLine();//見やすいように改行
Inherit Inherit = new Inherit();
Inherit.Test1();//InheritのTest1が呼ばれました
Inherit.Test2();//InheritのTest2が呼ばれました
Console.WriteLine();//見やすいように改行
ここはわかりやすいと思います。
それぞれの型のTest1およびTest2メソッドが呼ばれます。
Base Test = new Inherit();//継承元のクラスには、暗黙的に型変換できる
Test.Test1();//InheritのTest1が呼ばれました
Test.Test2();//BaseのTest2が呼ばれました
問題は最後のここです。
継承すると継承元のクラスには暗黙的に型変換できます。
ここでは、Inherit型でnewして、Base型の変数(Test)に暗黙的に型変換して代入しています。
さて、TestからTest1及びTest2を呼び出すとどうなるのか。
overrideで記述している場合(Test1)は、newした時の型(Inherit)のメソッドが呼ばれます。
そうでない場合(Test2)は、保存されている型(Base)のメソッドが呼ばれます。
"override"日本語で言うと、上書きです。
Baseで定義したTest1を、Inheritクラスで上書きしていることになります。
実は、このオーバーライドの動きを理解すると、オブジェクト指向の"多態性"という考えが理解できます。
例えば行列演算です。ソフトウェアはDeepLearningを行うソフトで、Test1は逆行列を計算するメソッドだったとします。
このとき、2×2くらいの小さい行列の演算を何度も行う場合と、100×100くらいの巨大な行列の演算を行う場合では、最適なアルゴリズムは違ってきます。GPUを使うかCPUを使うかでも最適なアルゴリズムは変わってくるでしょう。
例えばBaseでは小さい行列の演算に最適化されたアルゴリズムになっていて、Inheritが大きい行列に特化したアルゴリズムだとすると、オーバーライドをするだけで、DeepLearning全体の処理には変更を加えることなく、処理速度を上げることができます。