やる気がストロングZERO

やる気のストロングスタイル

【C#】virtual, override, new

下記のようなコードを書きたいときがある。(staffに複数形はないらしいがとりあえず無視)

Staff[] staffs = new Staff[2];
staffs[0] = new Alice();
staffs[1] = new Bob();
     
foreach(var staff in staffs){
     staff.who_am_i();
}

who_am_i()は自分の名前を表示する関数だとすると、 下記のような結果を期待する。

I'm Alice
I'm Bob

期待通りの動作をさせるには、正しくvirtualとoverrideを記述する必要がある。

public class Staff{
    public virtual void who_am_i(){
        System.Console.WriteLine("I'm staff");
    }
}
    
public class Alice : Staff{
    public override void who_am_i(){
        System.Console.WriteLine("I'm alice");
    }
}
    
public class Bob : Staff{
    public override void who_am_i(){
        System.Console.WriteLine("I'm bob");
    }
}

virtual, overrideを書かなかった場合、ビルド時に警告が出て、結果は下記のようになる。

I'm staff
I'm staff

意図的に上記のような結果にしたい場合はnewを使う

public class Staff{
    public virtual void who_am_i(){
        System.Console.WriteLine("I'm staff");
    }
}
    
public class Alice : Staff{
    public new void who_am_i(){
        System.Console.WriteLine("I'm alice");
    }
}
    
public class Bob : Staff{
    public new void who_am_i(){
        System.Console.WriteLine("I'm bob");
    }
}

どういうことか?

オーバーライドとは、基底クラスのメソッドを再定義するという事。
だから正しくオーバーライドされている場合、基底クラスの型(Staff型)でメソッドを読んだとき、再定義された処理が実行される。

virtualとoverrideを記載しないとメソッドがオーバーライドされない。

オーバーライドされない場合どういう状態かというと、
基底クラスとは別に派生クラス側で新しく同名のメソッドが定義された状態になる。
同名なので派生クラス側のメソッドが基底クラス側のメソッドを隠す形になる。

だから派生クラスの型(AliceとかBobとか)でメソッドを呼んだときは、派生クラスに定義された同名メソッドの処理が実行されるし、基底クラスの型でメソッドを呼んだときには、規定クラスに定義されている処理が走る。

意図的にオーバーライドをしない状態でメソッド定義したい場合にoverrideキーワードの代わりにnewキーワードを使う。