スイッチとは何ですか?

分岐のないプログラムは非常にシンプルで奇妙なプログラムです。 プログラムは考え、オプションを計算し、さまざまな外部の影響に対して異なる反応を示し、まったく均一ではないはずです。 そして、これはすべて分岐なしでは不可能です。 分岐は、ifおよびswitch演算子を使用して実装されます。 なぜ彼と戦う必要があるのですか?



定期的に、他の人のコードを表示すると、長いメソッドとネストされたifおよびswitchの面倒な構成に遭遇します。 たとえば、次のとおりです。



//     Objective C,           - (NSUInteger)numberOfItemsInSection:(NSUInteger)section { if (self.loggedIn) { swtich (section) { case 0: return 2; case 1: { if (self.settings.showDetails) { return 5; } else { return 3; } } case 2: return 3; } } else { swtich (section) { case 1: { if (self.settings.showDetails) { return 5; } else { return 3; } } case 2: return 3; } } }
      
      







個人的に、そのような方法は私を怖がらせ、それらは私の頭に収まりません。 最初に求めることは、すべてのマジックナンバーに名前を付けることです。 たとえば、次のように:



 enum SectionIndex { LoginSection = 0, DetailsSection, ExtendedSection }
      
      







ただし、よく見ると、self.loggedInに設定されている場合はLoginSectionを考慮せず、self.settings.showDetailsにリセットされている場合はDetailsS​​ectionを非表示にします。 ただし、現在の状態に基づいてセクション値をSectionIndexに変換するだけです。



 - (SectionIndex)sectionIndexForSection:(NSUInteger)section { if (!self.loggedIn) { ++section; } if (!self.settings.showDetails) { ++section; } return (SectionIndex)section; } - (NSUInteger)numberOfItemsInSection:(NSUInteger)section { SectionIndex sectionIndex = [self sectionIndexForSection:section]; switch (sectionIndex) { case LoginSection: return [self numberOfItemsInLoggedInSection]; case DetailsSection: return [self numberOfItemsInDetailsSection]; case ExtendedSection: return [self numberOfItemsInExtendedSection] } } }
      
      







私の意見では、特にオブジェクトに通常いくつかのブランチがあることを考慮すると、それはすでにずっと良く見えます。 たとえば、-titleForItem:inSection:、-performActionForItem:inSection:など。 しかし、言語がオブジェクト指向であり、システムの状態をオブジェクト状態にできることを思い出したらどうでしょうか? その後、これらのメソッドはすべて1行に削減されます-状態オブジェクトへのアクセス?



 - (NSUInteger)numberOfSections { retun [self.state numberOfSections]; } - (NSUInteger)numberOfItemsInSection:(NSUInteger)section { retun [self.state numberOfItemsInSection:section]; } - (NSString *)titleForItem:(NSUInteger)item inSection:(NSUInteger)section { retun [self.state titleForItem:item inSection:section]; } - (void)performActionForItem:(NSUInteger)item inSection:(NSUInteger)section { retun [self.state performActionForItem:item inSection:section]; }
      
      







私の意見では、それは非常に美しいです。 どこかからこの状態を取得するためだけに残ります。 オブジェクト自体に状態オブジェクトを構成するか、状態を定義するいくつかのクラスを記述できます。



 @interface State : NSObject @property (nonatomic, strong) NSArray *sections; // ... @end @implementation State - (NSUInteger)numberOfSections { return [self.sections count]; } - (NSUInteger)numberOfItemsInSection:(NSUInteger)section { return [self.sections[section] count]; } - (NSString *)titleForItem:(NSUInteger)item inSection:(NSUInteger)section { return self.sections[section][item][@"title"]; } - (void)performActionForItem:(NSUInteger)item inSection:(NSUInteger)section { void(^actionBlock)() = self.sections[section][item][@"action"]; actionBlock(); } //   - (void)setupForState { NSMutableDictionary *state = [NSMutableDictionary dictionary]; if (self.loggedIn) { [state addObject:[self loggedInSection]]; } if (self.showDetails) { [state addObject:[self detailsSection]]; } [state addObject:[self extendedSection]]; self.sections = state; } - (NSArray *)loggedInSection {...} - (NSArray *)detailsSection {...} - (NSArray *)extendedSection {...} // ...
      
      







ブランチを複数の場所で取り除き、1つの状態設定に置き換え、状態自体が統合され、理解可能で、1か所に集められたことがわかりました。



All Articles