The introduction
Continuing with the Swift documentation, we learned about Swift type conversion from the previous chapter: Type conversion, mainly using IS for type checking, as? And the as! Type conversion syntax for downcasting, type conversion for Any and AnyObject, and so on. Now, let’s learn about the Swift nested type. Due to the long space, here is a section to record, next, let’s begin!
Nested types
Enumerations are typically created to support the functionality of a particular class or structure. Similarly, it might be convenient to define utility classes and constructs purely for use in the context of more complex types. To achieve this, Swift allows you to define nested types that support enumerations, classes, and structs in the definition of the types they support.
To nest a type within another type, write its definition in outer braces around the type it supports. Types can be nested to any desired level.
Nested types in operation 1
The following example defines a structure called BlackjackCard that models the playing cards used in blackjack games. The BlackjackCard structure contains two nested enumerated types Suit and Rank. In blackjack, the trump card has the value of 1 or 11. This functionality is represented by a structure called Values nested in the Rank enumeration:
struct BlackjackCard { // nested Suit enumeration enum Suit: Character {case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "1001"} // Override Rank enumeration enum: Int { case two = 2, three, four, five, six, seven, eight, nine, ten case jack, queen, king, ace struct Values { let first: Int, second: Int? } var values: Values { switch self { case .ace: return Values(first: 1, second: 11) case .jack, .queen, .king: return Values(first: 10, second: nil) default: return Values(first: self.rawValue, second: nil) } } } // BlackjackCard properties and methods let rank: Rank, suit: Suit var description: String { var output = "suit is \(suit.rawValue)," output += " value is \(rank.values.first)" if let second = rank.values.second { output += " or \(second)" } return output } }Copy the code
The Suit enumeration describes the four common playing card sets and the original character values that represent their symbols. The Rank enumeration describes the 13 possible poker levels, along with the raw Int value that represents their face value. (This original Int value is not used for Jack, Queen, King, and Ace cards.) As mentioned above, the Rank enumeration defines another nested structure of its own, called Values. This structure encapsulates the fact that most cards have only one value, whereas Ace cards have two. The Values structure defines two attributes to represent this:
- first, of type Int
- second, of type Int? , or “optional Int”
Rank also defines a calculated property values, which returns an instance of the values structure. This calculation property considers the level of the card and initializes a new value instance with the appropriate value based on the level of the card. It uses special values for Jack, Queen, King, and ace. For digital cards, it uses the raw Int value of raw. The BlackjackCard structure itself has two properties rank and suit. It also defines a computed property called Description, which uses the values stored in rank and suit to build a description of the card’s name and value. The description attribute uses an optional binding to check if there is a second value to display, and if so, inserts additional description details for the second value.
Because BlackjackCard is a structure with no custom initializers, it has an implicit member-level initializer, as described in the member-level initializer for the structure type. You can use this initializer to initialize a new constant named theAceOfSpades:
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades) print("theAceOfSpades: \ [theAceOfSpades. The description)) / / Prints "" theAceOfSpades: suit is ♠, the value is 1 or 11"Copy the code
Even if Rank and Suit are nested in BlackjackCard, their type can be inferred from the context, so the initialization of this instance can reference enumeration cases only by their case names (.ace and.spades). In the example above, the description attribute correctly reports that the Ace of spades has a value of 1 or 11.
2 Reference nested types
To use a nested type outside its definition context, prefix its name with the name of the nested type:
Let heartsSymbol = BlackjackCard. Suit. Already. RawValue / / heartsSymbol is "♡"Copy the code
For the example above, this keeps the names of Suit, Rank, and Values short because their names are naturally qualified by the context in which they are defined.
Previous chapter: Type conversions Next chapter: Extensions
Swift-nested Types