- PR -

インタフェースと抽象クラスの混合は問題ない?

投稿者投稿内容
がらす
ベテラン
会議室デビュー日: 2005/07/14
投稿数: 99
投稿日時: 2006-06-08 10:48
いつもお世話になっております。
具体的なアルゴリズムクラスを作成してもらうためのベースクラス群を作ろうとしています。インタフェースに必要なメソッドを全て定義したのですが、ほとんどの具体的なアルゴリズムクラスで Initialize()メソッドの内容は共通なので、抽象ベースクラスを使ってデフォルトの動作を実装することにしました。以下のような状態です。
コード:
public interface IAlgorithm
{
    void Initialize();
    void Execute();
    void Abort();
}

public abstract class BaseAlgorithm
{
    public virtual void Initialize() {....}
}

public class MyAlgorithm : IAlgorithm, BaseAlgorithm
{
    public void Execute() {....}
    public void Abort() {....}
}



しかし、出来上がったコードを見て、最初から抽象ベースクラスのみを使って、デフォルト実装を提供しないものについては抽象メソッドにすれば全く同じではないかと思い始めました。こういう場合、どういうアプローチが良いのでしょうか?出来る限りインタフェースを使った方が良いと聞いてはいるのですが、まだ利点がわかっていないような気がします。
ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2006-06-08 11:22
インターフェイスは抽象メソッド郡なんだから。
外に切り出して再利用できるものはインターフェイス。
できないものは抽象メソッドとして切り分ければいい。
逆に継承構造上だけのものであればインターフェイスにする必要はない。
と僕は思う。
たつごろー
ぬし
会議室デビュー日: 2004/10/25
投稿数: 496
投稿日時: 2006-06-08 12:20
引用:

出来る限りインタフェースを使った方が良いと聞いてはいる


これの出典はどちらでしょう。
たぶん、「最近の言語では多重継承ができなくなってきたのでインタフェースの方がお得」、という意味の内容だったのではないかと想像します。(お得というのがかなり抽象的で大雑把な利点のアピールですが)
これは「インタフェースをどんどん使え」という意味ではありません。
ですので、無理にインタフェースを使う必要はありません。

インタフェースを使わずともクラスを使えばすっきりするんだけど、と感じているのでしたら、クラスで書けばいいと思いますよ。

_________________
たつごろー
codeseek
こみゅぷらす
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-06-08 12:42
引用:

出来る限りインタフェースを使った方が良いと聞いてはいるのですが


そういう意味での「インターフェース」は「interface」の事ではないですね。何と言うか、「抽象に依存せよ」とかそんな感じの意味です。
だから interface だろうが abstract だろうが 「インターフェース」なわけです。

という事で、
引用:

出来上がったコードを見て、最初から抽象ベースクラスのみを使って、デフォルト実装を提供しないものについては抽象メソッドにすれば全く同じではないかと思い始めました。


アリです。
_________________
囚人のジレンマな日々
lalupin4
大ベテラン
会議室デビュー日: 2004/07/26
投稿数: 163
投稿日時: 2006-06-08 12:52
コード:
public interface IAlgorithm
{
    ....
}

public abstract class BaseAlgorithm : IAlgorithm
{
   ....
}

public class MyAlgorithm : BaseAlgorithm
{
    ....
}

public class AlgorythmFactory
{
    public static IAlgorithm Get(string name)
    {
        ...
    }
}

public class AlgorithmClient
{
    public void AnyFunction()
    {
        IAlgorithm alg = AlgorithmFactory.Get("MyAlgolithm");
    }
}

 これでどうだ。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2006-06-08 12:54
引用:

がらすさんの書き込み (2006-06-08 10:48) より:
具体的なアルゴリズムクラスを作成してもらうためのベースクラス群を作ろうとしています。インタフェースに必要なメソッドを全て定義したのですが、ほとんどの具体的なアルゴリズムクラスで Initialize()メソッドの内容は共通なので、抽象ベースクラスを使ってデフォルトの動作を実装することにしました。以下のような状態です。


私はこういう場合は、interface を使わないほうが良いと思います。書かれているような「具体的なアルゴリズムクラスを作成してもらうため」という目的を考えると、abstract class で実現するのが自然です。
ただ、これは理論的な考え方であり、あとでプログラムを改造したいとか、そういう実践的な(ダーティーな)用途を考えると、interface のほうがいじりやすくて適していることもあります。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
まいるどきゃっと
大ベテラン
会議室デビュー日: 2004/08/12
投稿数: 135
お住まい・勤務地: 群馬
投稿日時: 2006-06-09 07:49
現在主流の言語では多重継承が禁止されていることが多いため、抽象クラスだと必ずそのクラスを継承しなければならないが、インターフェイスだとその制限はない。これが、抽象クラスではなく出来る限りインターフェイスを使えと言われる理由の中でわかりやすいものだとおもいます。

作ってもらうクラスは必ずBaseAlgorithmを継承してもらうということにして問題ないのでしたらIAlgorithmはいらなくなりますし、そういった制限をかけたくなければIAlgorithmは残しておいたほうがいいと思います。また、BaseAlgorithm以外に同様の別のクラス、例えばAnotherBaseAlgorithmみたいなものを作成してそちらを継承してもらうことを考えているのでしたら、IAlgorithmは残しておいたほうがいいでしょう。

インターフェイスにする利点は他にもありますが、まずはそういった見方をしてみてはいかがですか?
Elle
常連さん
会議室デビュー日: 2004/09/29
投稿数: 23
投稿日時: 2006-06-09 08:59
インタフェースは、「使い方の規定」。外部仕様のコード化。
クラスは「分類」。内部仕様のコード化。
抽象クラスは「細部未定の分類」。分類の共通部分。

抽象クラスとインタフェースでは表すものが違う(と思う)。

いくつものクラスを作る。これらは共通的な使い方が想定される。→使い方としてのインタフェースを作成。
それらは共通する部分があり、is_aで表現できる。→共通部分を抽象クラスで表現。
共通部分として使い方もある。→抽象クラスはインタフェースを実装する。

ということで、コード例としてはlalupin4さんと同じ意見です。
(ファクトリを作るかどうかはわかりませんが。)

別の言語ですが、Javaの標準ライブラリは、APIとしてそのように提供しているものがあります。
ユーザ(プログラマ)が作成したクラスは、規定のインタフェースを実装している必要がある。
但し、既にいくつかデフォルト実装がなされているものを用意しておくので、そちらを使ったほうが楽。
といった形です。

スキルアップ/キャリアアップ(JOB@IT)