導入
継承では、override で親のメソッドを置き換えるのが基本です。一方で、親と無関係に同じ名前を新しく定義し直すこともでき、それが new 修飾子です。また、子から親の実装を呼び出したいときは base を使います。混同しやすい2つを整理します。
説明
flowchart TB
P["親: Greet()"] -->|override| O["子: 親の呼び出しを置き換える<br/>(多態性が働く)"]
P -->|new| N["子: 同名の別メソッドを新設<br/>(親型で見ると親のまま)"]
style O fill:#e8f5e9
style N fill:#fff3e0
override は多態性が働き、親型の変数から呼んでも子の実装が動きます。new は「たまたま同名の別物」で、変数の型で呼ばれる側が決まります。base.Method() は親の実装を明示的に呼びます。
サンプル
Dog dog = new Dog();
Animal asAnimal = dog;
Console.WriteLine(dog.Speak()); // ワン(子の override)
Console.WriteLine(asAnimal.Speak()); // ワン(override は親型からでも子が動く)
Console.WriteLine(dog.Describe()); // 動物 / 犬(base で親を呼ぶ)
class Animal
{
public virtual string Speak() => "…";
public string Describe() => "動物";
}
class Dog : Animal
{
public override string Speak() => "ワン"; // 親を置き換える
public new string Describe() => base.Describe() + " / 犬"; // 親を呼びつつ拡張
}
override:親のvirtualを置き換える。親型の変数からでも子が動く(多態性)new:親と同名だが別物。呼ばれる側は変数の型で決まるbase.Member:子から親の実装を明示的に呼ぶ
やってみよう
Describe を new から virtual/override に変えると、Animal 型から呼んだときの結果がどう変わるかを試しましょう。多態性の有無の違いがはっきりします。
演習
class Base { public virtual string Name() => "base"; }
// TODO: Base を継承し、Name を override して base.Name() + "-child" を返す Child を定義してください
___
Console.WriteLine(new Child().Name()); // base-child
- 期待される出力:
base-child
ヒント1を見る
class Child : Base { public override string Name() => base.Name() + "-child"; }
ヒント2を見る
base.Name() で親の “base” を取得し、文字列連結します
まとめ
overrideは親を置き換え、多態性が働くnewは同名の別メソッド(呼ばれる側は変数の型で決まる)base.Memberで親の実装を呼べる
次回: 使い終わった資源を確実に片付ける IDisposable と using です。