本文へスキップ
BecomeCoder

C#オブジェクト指向コース · 第5章 オブジェクト指向の実践テクニック · レッスン38

メンバー隠蔽(new修飾子)と base

ブラウザで完結

導入

継承では、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:子から親の実装を明示的に呼ぶ

やってみよう

Describenew から 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 で親の実装を呼べる

次回: 使い終わった資源を確実に片付ける IDisposableusing です。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。