Add メソッドを「オーバーライド」して、より具体的な型を受け取るようにしても、インターフェイスが意味するコントラクトは実行されません。
Container インターフェースには次のメソッドがあると言います。
void Add(IComponent component);
void Add(IComponent component, string name);
ただし、EntityContainer インスタンス (IComponent を実装する) のみを許可する必要があるため、基本的には次のようにします。
void Add(EntityComponent component);
void Add(EntityComponent component, string name);
インターフェイスでは、IComponent を実装する任意の要素を追加できると言っているため、このような Container インターフェイスを (意味的にも) 実装することはできません。元の契約を変更している !
Morten がコメントで指摘したように、次のようなことができます。
class EntityContainer : Container {
void Add(IComponent component) {
var entityComponent = component as EntityComponent;
if(entityComponent == null)
throw new InvalidOperationException("Can only add EntityComponent instances");
// Actual add...
}
// Other methods..
}
しかし、そうしないことをお勧めします。インターフェイスが暗示する契約を破ることは、規則ではなく例外であるべきです。また、それを行うと、コンテナが実際に何を期待しているかを実行時まで知ることができません。これは直感的な動作ではなく、微妙な問題を引き起こす可能性があります。特定のタイプのコンポーネントのみを受け入れたい場合は、ジェネリックを使用できます。これにより、必要な制約を適用できるだけでなく、強い型付けが得られ、意図がより明確になります。次のようになります。
interface Container<T> where T : IComponent {
void Add(T component);
void Add(T component, string name);
}
これは、コンテナーが指定された型の要素を保持することを意味しますが、インターフェイス IComponent を実装 (またはクラスの場合は拡張) する必要があります。Container<Object>
IComponent を実装していないため、を作成することはできません。
EntityContainer は次のようになります。
class EntityContainer : Container<EntityComponent> {
void Add(EntityComponent component) {
// Actual add...
}
// Other methods..
}