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
,类型Int
second
,类型为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
的名称可以故意保持简短,因为它们的名字自然会被定义它们的上下文所限定。