プログラム内の if..else if..else ツリーを置き換えるまたは代用する最良の方法は何ですか? [closed] 質問する

プログラム内の if..else if..else ツリーを置き換えるまたは代用する最良の方法は何ですか? [closed] 質問する

この質問のきっかけは、最近よく目にするようになった構造ですif..else if..else。構造はシンプルで用途はありますが、もっときめ細かく、エレガントで、全体的に最新の状態に保つのが簡単なものに置き換えられるのではないかという気がしてなりません。

できるだけ具体的に言うと、次のようになります。

if (i == 1) {
    doOne();
} else if (i == 2) {
    doTwo();
} else if (i == 3) {
    doThree();
} else {
    doNone();
}

これを書き直す簡単な方法は 2 つ考えられます。1 つは三項演算子 (同じ構造を記述する別の方法) です。

(i == 1) ? doOne() : 
(i == 2) ? doTwo() :
(i == 3) ? doThree() : doNone();

または、Map (Java および C# でも)、Dictionary、またはその他の K/V 構造を使用して次のようにします。

public interface IFunctor() {
    void call();
}

public class OneFunctor implemets IFunctor() {
    void call() {
        ref.doOne();
    }
}

/* etc. */    

Map<Integer, IFunctor> methods = new HashMap<Integer, IFunctor>();
methods.put(1, new OneFunctor());
methods.put(2, new TwoFunctor());
methods.put(3, new ThreeFunctor());
/* .. */
(methods.get(i) != null) ? methods.get(i).call() : doNone();

実際、上記の Map メソッドは私が前回最終的に実行した方法ですが、この問題に対しては、一般的にもっと良い代替手段があるはずだと考えずにはいられません。

では、if..else if..else を置き換える他の方法 (おそらくより良い方法) にはどのようなものがあるでしょうか。また、あなたのお気に入りはどれでしょうか。

あなたの考えをこの行の下に書き込んでください!


さて、ここにあなたの考え:

まず、最も人気のある回答は次のような switch ステートメントでした。

switch (i) {
    case 1:  doOne(); break;
    case 2:  doTwo(); break;
    case 3:  doThree(); break;
    default: doNone(); break;
}

これはスイッチで使用できる値に対してのみ機能し、少なくとも Java では非常に制限的な要因となります。ただし、当然ながら、単純なケースでは許容されます。

あなたが提案しているもう 1 つの、おそらくもう少し手の込んだ方法は、ポリモーフィズムを使用することです。CMS によってリンクされている YouTube の講義は素晴らしいので、こちらでご覧ください。「クリーン コード トーク - 継承、ポリモーフィズム、テスト」私の理解する限りでは、これは次のように翻訳されます。

public interface Doer {
    void do();
}

public class OneDoer implements Doer {
    public void do() {
        doOne();
    }
}
/* etc. */

/* some method of dependency injection like Factory: */
public class DoerFactory() {
    public static Doer getDoer(int i) {
        switch (i) {
            case 1: return new OneDoer();
            case 2: return new TwoDoer();
            case 3: return new ThreeDoer();
            default: return new NoneDoer();
        }
    }
}

/* in actual code */

Doer operation = DoerFactory.getDoer(i);
operation.do();

Google の講演から 2 つの興味深い点が見つかりました。

  • null を返す代わりに Null オブジェクトを使用します (ランタイム例外のみをスローしてください)
  • if: を使わずに小さなプロジェクトを書いてみてください。

また、私の意見では、言及する価値がある投稿の 1 つは、CDR です。彼は、彼の倒錯した習慣を私たちに提供してくれました。使用することはお勧めしませんが、見るだけで非常に興味深いです。

皆さん、これまでの回答に感謝します。今日は何かを学べたかもしれません!

ベストアンサー1

これらの構造は、多くの場合、ポリモーフィズムによって置き換えられます。これにより、コードが短くなり、脆弱性が軽減されます。

おすすめ記事