列挙型+関連する値= Swift

Swiftは高速を意味します。 高速とは、明確でシンプルなことを意味します。 しかし、単純さと理解しやすさを実現するのは簡単ではありません。Swiftでは、コンパイル速度はまあまあで、言語のいくつかの側面から疑問が生じます。 それにもかかわらず、列挙の可能性(enum'ov)、私は(関連する値-添付値)について話します-最もクールなものの一つ。 これにより、コードを削減し、理解しやすく信頼性の高いものにすることができます。











最初のタスク



支払いオプションの構造を説明する必要があると想像してください:現金、カード、ギフト券、ペイパル。 各支払い方法には独自のパラメータがあります。 このような弱く定義された条件下では、実装オプションは無限であり、何かをグループ化したり、何かを再指定したりできます。 障害を見つける必要はありません。この構造は例としてここにあります。







class PaymentWithClass { // true,   ,  false ,  init()   var isCash: Bool = false // .some,   ,  -,  - var cardNumber: String? var cardHolderName: String? var cardExpirationDate: String? // .some,     var giftCertificateNumber: String? //  -     (    ) var paypalTransactionId: String? var paypalTransactionAuthCode: String? }
      
      





(何かがオプシュナルの多くを明らかにした)







そのようなクラスで働くのは難しいです。 Swiftは干渉します。これは、他の多くの言語とは異なり、すべてのophnalを強制的に処理するためです(たとえば、 if let



またはguard let



if let



)。 ビジネスロジックを隠す余分なコードがたくさんあります。







これを確認するのは不快です。 このクラスの有効性をチェックするコードを想像することはできますが、まったく書く気はありません。







構造!



Swiftには、構造体と呼ばれる値型があることを思い出してください。 彼らは、この種のモデル記述に使用するのが良いと言います。 前のコードを、さまざまなタイプの支払いに対応するいくつかの構造に分割してみましょう。







 struct PaymentWithStructs { struct Cash {} struct Card { var number: String var holderName: String var expirationDate: String } struct GiftCertificate { var number: String } struct PayPal { var transactionId: String var transactionAuthCode: String? } var cash: Cash? var card: Card? var giftCertificate: GiftCertificate? var payPal: PayPal? }
      
      





良くなった。 個々の支払いタイプの正確性は、言語自体を使用して確認されます(たとえば、PayPal認証コードが存在しないことがわかりますが、カードにはすべてのフィールドが必要です)。ゼロではありません。







便利ですか? かなり。 多くの言語のこの場所では、終わらせて、完了した作業を検討できます。 しかし、Swiftではそうではありません。







列挙型。 関連する値



Swiftは、他の現代言語と同様に、型付き列挙(enum)を作成する機能を提供します。 これらは、フィールドがいくつかの事前定義された値の1つである可能性があることを記述したり、 switch



に挿入してすべての可能なオプションが列挙されていることを確認する必要がある場合に便利に使用されます 理論的には、この例では、構造をより正確に検証するために、支払いタイプを挿入することが最大です。







 struct PaymentWithStructs { enum Kind { case cash case card case giftCertificate case payPal } struct Card { var number: String var holderName: String var expirationDate: String } struct GiftCertificate { var number: String } struct PayPal { var transactionId: String var transactionAuthCode: String? } var kind: Kind var card: Card? var giftCertificate: GiftCertificate? var payPal: PayPal? }
      
      





Cash



構造は消えており、空であり、現在明示的に入力したタイプを示すためにのみハングしていることに注意してください。 良くなった? はい、使用しているお支払い方法を簡単に確認できます。 明示的に登録され、どのフィールドがnil



でないかを分析する必要はありません。







次のステップは、どういうわけか、各タイプの個別のオファナルの必要性を取り除くことです。 対応する構造を型にバインドする機会があれば、それはクールです。 カード-番号と所有者、PayPal-トランザクション識別子など。







そのため、Swiftには関連付けられた値があります(関連付けられた値、プロトコルで使用される関連タイプと混同しないでください)。 次のように書かれています。







 enum PaymentWithEnums { case cash case card( number: String, holderName: String, expirationDate: String ) case giftCertificate( number: String ) case payPal( transactionId: String, transactionAuthCode: String? ) }
      
      





最も重要な点は、正確に定義された型です。 PaymentWithEnums



が4つの値のいずれか1つPaymentWithEnums



を取り、各値が特定のパラメーターをdateまたはtransactionAuthCode



として持つ(または持たない)ことはすぐに明らかです。 クラスまたは構造の場合に行うことができるように、カードと商品券の両方のパラメーターを一度に置くことは物理的に不可能です。







以前のオプションでは追加のチェックが必要であることがわかりました。 また、特に新しいオプションが表示された場合、支払いオプションの処理を忘れる可能性がありました。 列挙型はこれらの問題をすべて排除します。 新しいケースが追加された場合、次の再コンパイルではすべてのスイッチに追加する必要があります。 本当に必要な場合を除いてopshnalovはありません。







このような複雑な列挙型を通常どおり使用できます。







 if case .cash = payment { //  -     }
      
      





パラメーターは、パターンマッチングを使用して取得されます。







 if case .giftCertificate(let number) = payment { print("O_o  ! : \(number)") }
      
      





また、スイッチを使用してすべてのオプションをソートできます。







 switch payment { case .cash: print(" !") case .card(let number, let holderName, let expirationDate): let last4 = String(number.characters.suffix(4)) print(", !   \(last4), : \(holderName)!") case .giftCertificate(let number): print("O_o  ! : \(number)") case .payPal(let transactionId, let transactionAuthCode): print(" ! : \(transactionId)") }
      
      





演習として、クラス/構造バリアントに同様のコードを書くことができます。 演習を完了するために、あなたは怠けすぎて、誤ったオプションを含む必要なオプションをすべて処理する必要はありません。







バズ。 スイフト それはより速くコンパイルされ、一般に幸福があるでしょう。 :-)







少し熊手



列挙型は万能薬ではありません。 ここにあなたが出くわすかもしれないいくつかのものがあります。







まず、列挙型には格納されたフィールドを含めることはできません。 たとえば、支払い日(すべての支払いオプションで同じフィールド)をPaymentWithEnums



に追加する場合、エラーが発生します: enums may not contain stored properties



。 どうする? 列挙型の各ケースに日付を入れることができます。 構造体を作成し、そこに列挙型と日付を配置できます。







次に、通常の列挙型を==



演算子と比較できる場合(自動的に合成されます)、関連する値が表示されるとすぐに、比較の可能性が「消失」します。 これは簡単にEquatable



でき、 Equatable



プロトコルをサポートします。 ただし、その後で比較するのは不便です。 payment == PaymentWithEnums.giftCertificate



payment == PaymentWithEnums.giftCertificate



と書くことはできないので、正しい部分であるPaymentWithEnums.giftCertificate(number: "")



を作成する必要があります。 この場合、Boolを返す特別なメソッド( isGiftCertificate(_ payment: PaymentWithEnums) -> Bool



)を作成し、 if case



転送if case



方がはるかに便利です。 複数の値を比較する必要がある場合は、おそらくswitch



方が便利です。








All Articles