在另一个类型的范围内定义类型。 列举常用于支持特定类或结构的功能。同样,在更复杂的类型上下文中仅用于定义实用结构也是方便的,通常与特定类型一起使用的协议也是如此。为了实现这一点,Swift 允许定义嵌套类型,在这种情况下,您可以在支持它们的类型定义中嵌套诸如枚举、结构和协议等支持类型。
要在一个类型中嵌套另一个类型,将其定义写在支持它的外部类型的花括号内。类型可以嵌套到所需的任何级别。
嵌套类型的用法
以下示例定义了一个称为 BlackjackCard 的结构,用于模拟纸牌游戏 21 点中的纸牌。 BlackjackCard 结构包含两个嵌套的枚举类型 Suit 和 Rank 。
在 21 点游戏中,A 牌的价值可以是 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 枚举描述了十三种可能的扑克牌点数,以及一个原始的 Int 值来表示它们的面值。(这个原始的 Int 值不用于 J、Q、K 和 A 牌。)
如上所述, Rank 枚举定义了其自身的进一步嵌套结构,称为 Values 。该结构封装了大多数牌只有一个价值,但 A 牌有两个价值的事实。 Values 结构定义了两个属性来表示这一点:
first,类型为Intsecond,类型为Int?,或者“可选的Int”
Rank 还定义了一个计算属性 values ,它返回一个 Values 结构的实例。此计算属性会考虑牌的等级,并根据其等级初始化一个新的 Values 实例,使用特定值表示 jack 、 queen 、 king 和 ace 。对于数值牌,它使用牌等级的原始 Int 值。
BlackjackCard 结构本身有两个属性—— rank 和 suit 。它还定义了一个名为 description 的计算属性,该属性使用 rank 和 suit 中存储的值来构建牌名和牌值的描述。 description 属性使用可选绑定检查是否存在第二个值以显示,并在存在时插入额外的描述细节。
因为 BlackjackCard 没有自定义初始化器,所以它有一个隐式的成员 wise 初始化器,如结构类型成员 wise 初始化器中所述。你可以使用这个初始化器来初始化一个新的常量 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 的名字可以故意保持简短,因为它们的名字在定义时自然地由上下文限定。