インタフェースの命名パターンから知るインタフェースの役割

# はじめに

**C#**における(≒**.NET**における)インタフェースの命名パターンを個人的に整理するとともに、それぞれの**インタフェースの役割と存在意義**を考えてみます。

---

# 標準ライブラリのインタフェース

---

## パターン1 : `I` + `動詞-able`

単一のメソッドを定義するインタフェースはこのように命名されることが多いです。
**『〇〇できる』**の意味のインタフェースですので、メソッドもそれに応じたものを持ちます。

- 例
    - `System.IDisposable`
    - `System.IComparable<T>`
    - `System.Collections.Generic.IEnumerable<T>`

---

### サブバターン1-1

動詞と同名のメソッドを1つだけ持つパターンです。
個人的な見解ですが、**このパターンがインタフェースの基礎である**、と考えるとインタフェースそのものの理解がしやすいと思います。

```csharp
// 『破棄できる』インタフェース
public interface IDisposable {
    // 《自分自身を》破棄する
    void Dispose();
}
```
```csharp
// 『比較できる』インタフェース
public interface IComparable<in T> {
    // 《自分自身を》T型の他のオブジェクトと『比較する』
    int CompareTo(T other);
}
```

---

### サブバターン1-2

別のオブジェクトを取得するメソッドを1つだけ持つパターンです。
取得したオブジェクトは後述の_サブパターン2-2_のインタフェースを持ちます。
**動詞で表される操作が複雑**な場合に利用されます。

```csharp
// 『列挙できる』インタフェース
public interface IEnumerable<out T> {
    // 『《自分自身を》「列挙する人」を取得する』
    IEnumerator<T> GetEnumerator();
}
// ややこしいので非ジェネリクスのIEnumerableの継承は省略
```

---

## パターン2 : `I` + `動詞-or/動詞-er`

**『〇〇する者』**を意味するインタフェースです。
サブパターンによって性質が少し異なります。

- 例
    - `System.ICustomFormatter`
    - `System.Collections.Generic.IEnumerator<T>`

---

### サブバターン2-1

動詞と同名のメソッドを1つだけ持つパターンです。
_サブパターン1-1_に似ていますが、動詞の**対象が別オブジェクト**であることが大きく違います。

```csharp
// 『フォーマットする人』インタフェース
public interface ICustomFormatter {
    // 受け取った引数を元に『フォーマットする』
    String Format (String format, Object arg, IFormatProvider formatProvider);
}
```

---

### サブバターン2-2

メソッドが複数含まれているパターンです。
複数のメソッドを組み合わせて、1つの機能を実現します。
操作対象から予め**操作を任されている**、とも取れます。

```csharp
// 『列挙する人』インタフェース
public interface IEnumerator<out T> : IDisposable {
    // 《列挙する対象を》次の要素へ移動する
    bool MoveNext();
    // 《列挙する対象を》現在の要素を取得する
    T Current { get; }
    // 《列挙する対象を》初期状態に戻す
    void Reset();
}
// ややこしいので非ジェネリクスのIEnumeratorの継承は省略
```

---

## パターン3 : `I` + `名詞`

名詞に対応する**標準的なクラスの操作を定義**したものです。
このパターンのインタフェースは良く設計されていると強力です。

- 例
    - `System.Collections.Generic.IList<>`
    - `System.Collections.Generic.ICollection<>`

```csharp
// 『コレクション』を表すインタフェース
public interface ICollection<T> : IEnumerable<T> {
    // 《自分自身の》持つ要素数
    int Count { get; }
    // 《自分自身が》読み取り専用か否か 
    bool IsReadOnly { get; }
    // 《自分自身に》T型の新しい要素を追加する
    void Add(T item);
    // 《自分自身の》要素を空にする
    void Clear();
    // 《自分自身に》対象の要素が含まれているか判断する
    bool Contains(T item); 
    // 《自分自身の》arrayIndex番目の要素以降をarrayにコピーする                
    void CopyTo(T[] array, int arrayIndex);
    // 《自分自身から》対象の要素を削除する 
    bool Remove(T item);
}
```

```csharp
// 『リスト』を表すインタフェース
// 『リスト』は『コレクション』に加えて以下のことが可能
public interface IList<T> : ICollection<T> {
    // 《自分自身の》index番目の要素を取得、設定する
    T this[int index] { get; set; }
    // 《自分自身の》何番目に対象の要素があるか判断する
    int IndexOf(T item);
    // 《自分自身の》index番目に対象の要素を挿入する
    void Insert(int index, T item);
    // 《自分自身の》index番目の要素を削除する
    void RemoveAt(int index);
}
```

ちなみに、`LinkedList` は `ICollection<T>` は実装するけれど、 `IList<T>`は実装していません。このあたりも掘り下げてみると面白そうですね。

---

# 自作する場合

さて、各パターンを使った自作インタフェースの例を挙げることで、想像の幅を広げてみましょう。

---

## 1-1

_サブパターン1-1_　はシンプルですね。この例のほかにも、動物を例にした_IFlyable(飛べる)_インタフェースなんかも例えに向いています。

```csharp
// 『印刷できる』
interface IPrintable {
    // 《自分自身を》印刷する
    void Print();
}

// 例えば、印刷できるドキュメント型
class Document : IPrintable { /*...*/ }
```

---

## 2-1

_サブパターン2-1_ もシンプルです。メソッドが**引数を持つ**のが特徴ですね。

```csharp
// 『カッター(切るもの)』
interface ICutter {
    // 《他のものを》切る
    Paper[] Cut(Paper paper);
}

// 例えば、他の物を切ることができるハサミ型
class Scissor : ICutter { /*...*/ }
```

---

## 1-2 と 2-2

_サブパターン1-2,2-2_ はイメージを膨らませるために、合わせて作ってみました。
**「テレビ」と「リモコン」みたいなイメージ**が個人的にはしっくりきます。
一つのテレビに対して複数のリモコンを作れるのは、少し感覚が違うかもしれませんね。より良い例えを思いついたら更新します(^^;

```csharp
// 『リモコンで操作できる』
interface IRemoteControllable {
    // 《自分自身を》操作するためのリモコンを取得する
    IRemoteController GetController();
}
// 『リモコン(遠隔操作するもの)』
interface IRemoteController {
    // 『《遠隔操作する対象の》電源を入切する』
    void Power(bool turningOn);
    // 『《遠隔操作する対象の》チャネルを変更する』
    void ChangeChannel(int channel);
}

// リモコン操作可能なテレビ型
class Television : IRemoteControllable {

    bool _powerOn;
    int _channel;

    // 自分自身を対象とするリモコンを返却
    public IRemoteController GetController() {
        return new RemoteController(this);
    }

    // リモコン型
    class RemoteController : IRemoteController {

        Television _television;

        // コンストラクタで対象のテレビを受け取る
        public RemoteController(Television television) {
            _television = television;
        }

        public void ChangeChannel(int channel) {
            _television._channel = channel;
        }

        public void Power(bool turningOn) {
            _television._powerOn = turningOn;
        }
    }
}
```

---

## 3

_パターン3_ はメソッドが多いパターンで、教科書的な説明ではこのパターン3が使われることも多いです《`IList<int> list = new List<int>();`のようなパターン》
一方で、このパターンで説明すると、インタフェースの意義は分かりにくかったりします。

もしあなたがオブジェクト指向言語の教育係になったなら、このパターンではなく、サブパターン1-1のようなインタフェースを例として挙げることをお勧めします。

ちょっと否定的な書き方をしてしまいましたが、それでも**DIなどで出番が多い**のがこのパターンです。上手く付き合ってインタフェースのスペシャリストになりましょう。

以下、良い例とは言い難いのですが、例を示しておきます。

```csharp
// 『車』
interface ICar {
    // 『《自分自身の》エンジンを開始する』
    void StartEngine();
    // 『《自分自身を》加速する』
    void Accel();
    // 『《自分自身を》減速する』
    void Break();
}

// 様々な車
class Car : ICar { /* ・・・*/ }
class Bus : ICar { /* ・・・*/ }
```

---

# まとめ

|No| パターン | 特徴 |Method|
|:--:|:--:|:--|:--:|
|1-1| -able | 動詞と同名のメソッド |少|
|1-2| -able | 複雑な操作をする別オブジェクト<br>_(パターン2-2)_を生成する |少|
|2-1| -or / -er | 他のオブジェクトを操作するメソッド |少|
|2-2| -or / -er | 状態を管理するメソッド |多|
|3| 名詞 | 一揃いのメソッド群 |多|

上記以外の例もあるとは思いますが、大雑把な分類としては有効でしょう。

---

## 今回まとめられてないパターン

今回は省略したパターン
今後何かで記事を書くかもしれません…

- `System.ComponentModel.INotifyPropertyChanged`
    - *Notify* なので、動詞句型の命名
    - `PropertyChanged` という`event`を持つ

---

# おわりに

命名パターンごとに、少しずつ性格が違うインタフェースであることが分かります。標準のクラスライブラリを学習する場合にも、***命名に着目することで理解がより容易になる***と思います。
また、自分でインタフェースを設計するときには、***命名を考えることで設計の手助けになる***はずです。

---

- 偉そうに書いていますが、色々と突っ込みを頂けると嬉しいです！
- 誤字脱字から高度な内容まで、なにかあればコメントお願いします。