- インターフェース: 実装クラスに複数適用可能、実装本体を記述できない(*)
- 抽象クラス: 実装クラスに複数適用できない、実装本体を記述できる
*) 最近はデフォルト実装を記述できる言語もある。C#では どうだろう 8.0 (.NET Core 3.0) から利用可能。
どちらも利用者クラスにおいて実装インターフェースや抽象クラスと置き換え可能(リスコフの置換原則)。なので適当なFactory で生成したオブジェクトを定義したインターフェースや抽象クラス扱いできる。
例
インターフェース は以下が許される
public interface IFoo{
void DoFoo();
}
public interface IBar{
void DoBar();
}
public class FooService: IFoo, IBar{
public void DoFoo(){
}
public void DoBar(){
}
}
一方抽象クラスはは以下が許されない
public abstract class AbstractFoo{
public abstract void DoFoo();
}
public abstract class AbstractBar{
public abstract void DoBar();
}
public class FooService: AbstractFoo, AbstractBar{
public void DoFoo(){
}
public void DoBar(){
}
}
使い分け
複数インターフェースを実装する局面も IDisposable を付けるとか意外はほとんどないし、実際抽象クラスだけでどうにかなる場合も多いので明確な使い分け指針があるわけでもない。
ただDI使う場合Containerへの登録等でインターフェースを定義する必要がある場合が多いかも。