読者です 読者をやめる 読者になる 読者になる

ポリモーフィックなメソッド

C# .NET Memo

C#ポリモーフィックなメソッドに関して、Javaに比べて少し複雑になっている。

using System;

class Base
{
    public void Method()
    {
        Console.WriteLine("base class");
    }
}

class Sub : Base
{
    public void Method()
    {
        Console.WriteLine("sub class");
    }
}

class Program
{
    static void BaseMethod(Base b)
    {
        b.Method();
    }

    static void SubMethod(Sub s)
    {
        s.Method();
    }

    static void Main(string[] args)
    {
        BaseMethod(new Base());
        SubMethod(new Sub());

        BaseMethod(new Sub());
    }
}

これの実行結果は、


base class
sub class
base class

となる。メソッドをオーバーライドしたい場合、スーパークラスのメソッドにvirtualを、サブクラスのメソッドにoverrideを指定する必要がある。

virtualなし virtualあり
overrideあり コンパイルエラー オーバーライド
overrideなし 隠蔽 隠蔽

隠蔽はnewキーワードを使って明示的にやれとの警告が出る。


あと、クラス階層が3階層以上の場合、上の階層でvirtualが指定されていればそれより下の階層は全部overrideとしていする*1
例えば、

class SubSub : Sub
{
    public override void Method()
    {
        Console.WriteLine("sub sub class");
    }
}

これを追加すれば、BaseMethod(new SubSub())とやってもSubMethod(new SubSub())とやってもsub sub classと表示される。


base class
sub class
sub class
sub sub class
sub sub class

ここら辺の明示的に指定する方法、昔は嫌いだったんだけど、間違いを見つけやすくする、って言う点で今はかなり好きだ。いっそ、newキーワードを使わずに隠蔽もエラーにしてしまってもいいくらい。ビバ冗長。

追記:
virtualとoverrideとかnewとoverrideは同居出来ないけど、newとvirtualは同居可能。
例えば、上のプログラムのSubクラスを

class Sub : Base
{
    public new virtual void Method()
    {
        Console.WriteLine("sub class");
    }
}

に変更すると、


base class
sub class
base class
base class
sub sub class

となる。

*1:virtualとoverrideは同時に指定出来ない