Swift基础 - 嵌套类型
翻译自:https://docs.swift.org/swift-book/LanguageGuide/NestedTypes.html
创建枚举通常是为了支持特定类或结构的功能。同样,可以方便地定义纯属实用程序类和结构,以便在更复杂类型的上下文中使用。为了做到这一点,Swift使您能够定义嵌套类型,从而在它们支持的类型的定义中嵌套支持枚举、类和结构。
要将类型嵌套在另一种类型中,请在它支持的类型的外部大括号中写入其定义。类型可以嵌套到所需的任意级别。
嵌套类型在行动
下面的示例定义了一个名为BlackjackCard结构,该结构模拟了二十一点游戏中使用的扑克牌。BlackjackCard结构包含两种嵌套枚举类型,称为Suit和Rank。
在二十一点中,Ace卡的价值为1或11。此功能由一个名为Values结构表示,该结构嵌套在Rank枚举中:
- struct BlackjackCard {
- // nested Suit enumeration
- enum Suit: Character {
- case spades = “♠”, hearts = “♡”, diamonds = “♢”, clubs = “♣”
- }
- // nested Rank enumeration
- enum Rank: 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
- }
- }
Suit枚举描述了四套常见的扑克牌套装,以及代表其符号的原始Character值。
Rank枚举描述了13个可能的扑克牌排名,以及表示其面值的原始Int值。(此原始Int值不用于Jack、Queen、King和Ace卡。)
如上所述,Rank枚举定义了自己的进一步嵌套结构,称为Values。这种结构概括了一个事实,即大多数卡片只有一个值,但Ace卡有两个值。Values结构定义了两个属性来表示这一点:
first,类型Intsecond,类型为Int?,或“optionalInt”
Rank还定义了一个计算属性,即values,它返回Values结构的实例。此计算属性考虑卡的排名,并根据排名使用适当的值初始化一个新的Values实例。它为jack、queen、king和ace使用特殊值。对于数字卡,它使用排名的原始Int值。
BlackjackCard结构本身有两个属性——rank和suit。它还定义了一个名为description计算属性,该属性使用rank和suit中存储的值来构建卡片名称和值的描述。description属性使用可选绑定来检查是否有第二个值要显示,如果是,则为第二个值插入额外的描述细节。
由于BlackjackCard是一个没有自定义初始化器的结构,因此它有一个隐式成员初始化器,如结构类型的成员初始化器中所述。您可以使用此初始化器初始化名为theAceOfSpades的新常量:
- let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
- print(“theAceOfSpades: (theAceOfSpades.description)”)
- // Prints “theAceOfSpades: suit is ♠, value is 1 or 11”
即使Rank和Suit嵌套在BlackjackCard中,它们的类型可以从上下文中推断出来,因此此实例的初始化只能通过它们的大小写名称(.ace和.spades)来引用枚举案例。在上面的示例中,description属性正确地报告黑桃王牌的值为1或11。
提及嵌套类型
要在其定义上下文之外使用嵌套类型,请在其名称前加上嵌套在其中的类型名称:
- let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
- // heartsSymbol is “♡”
对于上面的例子,这使Suit、Rank和Values的名称可以故意保持简短,因为它们的名字自然会被定义它们的上下文所限定。


