LoginSignup
11
12

More than 5 years have passed since last update.

インターフェースの暗黙的実装を隠ぺいするとどうなるか

Last updated at Posted at 2014-05-28

以下のようなクラス構造を作るとどう動作するのか、ちょっと自信が無かったので確認。

// 基底クラスであるインターフェースを実装
public class Animal : IHogerable
{
    public void DoHoge()
    {
        Console.WriteLine("Animal");
    }
}

// 派生クラスで同じインターフェースを実装
public class Dog : Animal, IHogerable
{
    // new は無くても動作は同じ。new が無い場合は警告が出る。
    public new void DoHoge()
    {
        Console.WriteLine("Dog");
    }
}

public interface IHogerable
{
    void DoHoge();
}

これらを IHogerable 型の変数経由で呼び出すとどうなるか?
もちろん、Animal 型の変数や Dog 型の変数経由で呼び出した場合はそれぞれのメソッドが呼ばれる。

var animal = new Animal();
animal.DoHoge(); // Animal.DoHoge が呼ばれる
var dog = new Dog();
dog.DoHoge(); // Dog.DoHoge が呼ばれる

foreach (var hogerable in new IHogerable[] { animal, dog })
{
    hogerable.DoHoge(); // どっちのメソッドが呼ばれる???
}
実行結果
Animal
Dog
Animal
Dog

InterfaceMethodHide.png

IHogerable 型の変数経由で呼び出した場合、インスタンスの型に応じて呼び出されるメソッドが変わる。


なお、Dog クラスの宣言で明示的に : IHogerable を書くか書かないかで動作が変わる。

public class Dog : Animal // IHogerable の実装を宣言しない
{
    public new void DoHoge() // 単に Animal.DoHoge の実装を隠ぺいする
    {
        Console.WriteLine("Dog");
    }
}

こうすると

実行結果
Animal
Dog
Animal
Animal

IHogerable 経由で呼び出した場合に Animal.DoHoge の方が呼ばれるようになる。
つまり、Dog クラスで IHogerable の実装を上書きする意図があるかないかをくみ取ってくれる。

よく考えられているなぁ……


さらに確認した内容を追記します。

Q. インターフェースに複数のメンバーが定義されている場合は?

A. Dog で隠ぺいした分はそちらが、隠ぺいしていない分は Animal のメンバーが呼び出されます(つまり一部だけを隠ぺいすることが可能)

Q. Animal クラスで暗黙的な実装と明示的な実装の両方がある場合は?

A. IHogerable 型経由で Dog インスタンスのメンバーを呼び出した場合、以下の優先順で呼ばれます。直感通りです

  • Dog クラスの明示的実装
  • Dog クラスの隠ぺいしている暗黙的実装
  • Animal クラスの明示的実装
  • Animal クラスの暗黙的実装
11
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12