C#で基底クラスのメソッドを置き換えるオーバーライド

C#

オーバーライドとは基底クラスのメソッドを派生クラスで再定義する事です。
派生クラスを作成する時、基底クラスの機能の一部をちょっと変えたいなという時に使用します。

オーバーライドを使いこなすためには「virtual」「new」「override」という3つのキーワードを理解する必要があります。

※C++でもオーバーライドの機能があり同じようにvirtualキーワードを使いますがC#とは仕様が少し異なります
※C#での動きを正しく理解して使いこなしましょう



virtualキーワード

virtual キーワードは基底クラスで使用します。
このメソッドは派生クラスでメソッドの再定義 (override) をしても構わないですよという意味になります。

※virtual キーワードを定義せずに派生クラスで override を使おうとするとコンパイルエラーになります

    public class TestBase
    {
        public virtual void Test()
        {
            System.Console.WriteLine("TestBase.Test()");
        }
    }


new キーワード

new キーワードは派生クラスで使用します。
派生クラスでメソッドを再定義する場合「new」か「override」のどちらかを使って定義する事になりますが、どちらを使うかでメソッドの呼ばれ方が変わってきます。

  • new   ・・・ 変数の型によってメソッドが呼び分けられる
  • override ・・・ 必ずインスタンスの型のメソッドが呼び出される

new は変数の型によって基底クラスのメソッドが呼ばれるか派生クラスのメソッドが呼ばれるかが変わります。つまり基底クラスのキャストした後にメソッドを呼び出すと基底クラスのメソッドが使われます。

基底クラスへキャストした時の例


    public class TestBase
    {
        public void Test()
        {
            System.Console.WriteLine("TestBase.Test()");
        }
    }

    public class TestDerived : TestBase
    {
        public new void Test()
        {
            System.Console.WriteLine("TestDerived.Test()");
        }
    }


    static void Main(string[] args)
    {
        TestDerived testD = new TestDerived();
        TestBase    testB = testD;

        testD.Test();
        testB.Test();
    }

結果は以下の通りです。

TestDerived.Test()
TestBase.Test()


「TestBase」へキャストした「testB」では基底クラスのメソッドが呼ばれる事が分かります。

クラス内からメソッドが呼ばれる例


    public class TestBase
    {
        public void Test()
        {
            System.Console.WriteLine("TestBase.Test()");
        }

        public void Call()
        {
            Test();
        }
    }

    public class TestDerived : TestBase
    {
        public new void Test()
        {
            System.Console.WriteLine("TestDerived.Test()");
        }
    }


    static void Main(string[] args)
    {
        TestDerived testD = new TestDerived();
        TestBase    testB = testD;

        testD.Call();
        testB.Call();
    }

結果は以下の通りです。

TestBase.Test()
TestBase.Test()

この例では基底クラスにある Call メソッドから Test メソッドが呼び出されています。
派生クラスのインスタンスである「testD」から Callメソッドを呼び出しても基底クラスの Test メソッドが呼び出される事が確認できます。



override キーワード

override キーワードは派生クラスで使用します。
派生クラスでメソッドを再定義する場合「new」か「override」のどちらかを使って定義する事になりますが、どちらを使うかでメソッドの呼ばれ方が変わってきます。

  • new   ・・・ 変数の型によってメソッドが呼び分けられる
  • override ・・・ 必ずインスタンスの型のメソッドが呼び出される

override はインスタンスの型のメソッドが呼ばれます。
基底クラスへキャストしたとしても、基底クラスから再定義されたメソッドが呼びだされたとしてもインスタンスを作成したクラスのメソッドが使われます。

※基底クラスで virtual キーワードを定義せずに override を使おうとするとコンパイルエラーになります

    public class TestBase
    {
        public virtual void Test()
        {
            System.Console.WriteLine("TestBase.Test()");
        }

        public void Call()
        {
            Test();
        }
    }

    public class TestDerived : TestBase
    {
        public override void Test()
        {
            System.Console.WriteLine("TestDerived.Test()");
        }
    }


    static void Main(string[] args)
    {
        TestDerived testD = new TestDerived();
        TestBase    testB = testD;

        testD.Test();
        testB.Test();
        testD.Call();
        testB.Call();
    }

結果は以下の通りです。

TestDerived.Test()
TestDerived.Test()
TestDerived.Test()
TestDerived.Test()



基底クラスのメソッドを呼び出す

メソッドをオーバーライドする時、基底クラスの処理にちょこっと付け足すだけような場合は改めてコードを書き直すより基底クラスのメソッドを呼び出したいと思うかもしれません。
そんな時は base キーワードを使いましょう。

    public class TestDerived : TestBase
    {
        public override void Test()
        {
            base.Test();                                       // ←ココ
            System.Console.WriteLine("TestDerived.Test()");
        }
    }



コメント