Birden çok if -'s'de bayrak nasıl kullanılır?


10

Bu benim kod ve diğerleri yeterince sık görmek gibi görünüyor. Bu konuda korkunç görünen hiçbir şey yok, ama daha iyi yapılabileceği gibi beni rahatsız ediyor. Bir vaka ifadesi varsayalım, biraz daha mantıklı olabilir, ancak çoğu zaman değişken iyi veya vaka ifadeleriyle (dile bağlı olarak) çalışmayan bir türdür

If variable == A
    if (Flag == true)
        doFooA()
    else
        doFooA2

else if variable == B
    if (Flag == true)
        doFooB()
    else
        doFooB2
else if variable == C
    if (Flag == true)
        doFooC()
    else
        doFooC2

Görünüşe göre bunu "çarpanlarına ayırmanın" birçok yolu vardır, örneğin 2 set if-elses, burada bir küme Flag == true olduğunda işlenir.

Bunu hesaba katmanın "iyi bir yolu" var mı, belki de bu if-else algoritması gerçekleştiğinde genellikle yanlış bir şey yaptığınız anlamına mı gelir?


6
Flag değişkenini bayrağın kendisi ile başa çıkabilecek doFooX'a geçirmek mümkün olabilir mi?
Jean-François Côté

emin ama sonra sadece doFooX, bayrağının doğru olup olmadığını değerlendirir ve sonra da doFooX1 veya doFooX2
TruthOf42

5
IMHO, okumaya devam edecek. Sonra doFooA ve doFooA2 ne yapar bağlıdır ...
Jean-François Côté

2
Neden if (Flag == true)sadece yazmak yerine If (Flag)? Bunun If (Flag == true)daha iyi olduğunu düşünüyorsanız , neden olmasın if ((Flag == true) == true)?
Keith Thompson

1
Aşağıdaki cevapların çoğundan en önemli çıkarımı, mantıksal akış ve geleceğin kodunun korunması söz konusu olduğunda , basitliğin ve okunabilirliğin akıllı hilelerden çok daha önemli olmasıdır .
Patrick Hughes

Yanıtlar:


18

Polimorfizm ile halledilebilir.

factory(var, flag).doFoo();

Bir şeyin türünü if / else kontrol ettiğinde, if / else check değerini bir fabrika yönteminde merkezileştirebilir, daha sonra doFoo () yöntemini polimorf olarak çağırabilirsiniz. Ancak bu, 1 seferlik bir çözüm için aşırı öldürme olabilir.

Belki de anahtarın var / flag olduğu bir anahtar / değer haritası oluşturabilirsiniz ve değer işlevin kendisidir.

do[var, flag]();

2
+1: Tablo aramaları, neredeyse her seferinde iç içe if ifadelerini yendi.
kevin cline

1
Bunun en iyi çözüm olduğunu söylemek istiyorum.
Muffin Adam

6

Birden çok iç içe geçmiş ifs, kodun siklomatik karmaşıklığını artırır. Yakın zamana kadar, bir fonksiyonda birden fazla çıkış noktasına sahip olmak kötü yapılandırılmış kod olarak kabul edildi, ancak şimdi, kod basit ve kısa olduğu sürece , bunu kodun okunmasını önemsiz hale getirebilirsiniz:

    if (variable == A && Flag) {
        doFooA();
        return;
    }

    if (variable == A) {
        doFooA2();
        return;
    }

    if (variable == B && Flag){
        doFooB();
        return;
    }

    if (variable == B){
        doFooB2();
        return;
    }

    if (variable == C && Flag){
         doFooC();
         return;
    }

    if (variable == C){
         doFooC2();
    }

    return;

3

başka bir seçenek ise if ve switch öğelerini birleştirmektir. Bu, iç içe geçmiş tekniğinizden daha üstün değildir, ancak yinelenen testlerin sayısını azaltabilir (anahtar bir atlama tablosuna optimize edilirse).


if (flag)
{
    switch (variable)
    {
        case A:
           ... blah
           break;

        case B:
           ... blah
           break;

        case C:
           ... blah
           break;

        default:
           ... log an error.
           ... maybe do a default action.
           break;
    }
}
else // flag == false
{
    switch (variable)
    {
        case A:
           ... blah
           break;

        case B:
           ... blah
           break;

        case C:
           ... blah
           break;

        default:
           ... log an error.
           ... maybe do a default action.
           break;
}

0

Her zaman bu var ...

if variable == A && Flag
    doFooA()
else if variable == A 
    doFooA2    
else if variable == B && Flag
    doFooB()
else if variable == B
    doFooB2
else if variable == C && Flag
     doFooC()
else if variable == C
     doFooC2

Ama açıkçası, orijinal kodun ilk etapta yarı kötü olmadığını düşünüyorum.


0

Çok biçimlilik ve ruledizi kullanma

interface IRule() {
  boolean applicable(args...);
  obj apply(args...);
}

static final Array<IRule> rules = [new MeaningfulNameRule1(), new MeaningfulNameRule2(), ...];

/* where */
class MeaningfulNameRuleX extends IRule{ /* */ }

/* In your method */

for (rule in rules) {
  if (rule.applicable(a,b,c)){
    return rule.apply(e,f,g);
  }
}

Veya mike30önerildiği gibi: Kural koşulları kolayca bir anahtar oluşturabilirse, hashmap gitmek için en iyi yoldur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.