在另一个类型的范围内定义类型。 列举常用于支持特定类或结构的功能。同样,在更复杂的类型上下文中仅用于定义实用结构也是方便的,通常与特定类型一起使用的协议也是如此。为了实现这一点,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
,类型为Int
second
,类型为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
的名字可以故意保持简短,因为它们的名字在定义时自然地由上下文限定。