枚举通常用于支持特定类或结构的功能。类似地,可以方便地定义纯粹用于更复杂类型上下文中的实用程序类和结构。为了实现这一点,Swift允许您定义嵌套类型,您可以在它们所支持的类型的定义中嵌套支持枚举、类和结构。
要将类型嵌套在另一个类型中,请将其定义编写在其支持的类型的外部大括号中。类型可以嵌套到所需的任意级别。
Nested Types in Action 运行中的嵌套类型
下面的示例定义了一个名为BlackjackCard的结构,它为Blackjack游戏中使用的扑克牌建模。BlackjackCard结构包含两个嵌套的枚举类型,分别称为Suit和Rank。
在Blackjack中,王牌的值不是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枚举描述了四种常见的扑克牌花色,以及表示它们符号的原始字符值。
Rank枚举描述了十三种可能的扑克牌等级,以及表示其面值的原始Int值。(此原始Int值不用于Jack、Queen、King和Ace卡。)
如上所述,秩枚举定义了它自己的进一步嵌套结构,称为值。这个结构封装了这样一个事实:大多数卡片只有一个值,而Ace卡有两个值。value结构定义了两个属性来表示:
- Int
- Int?
Rank还定义了一个计算属性values,它返回values结构的实例。此计算属性考虑卡片的秩,并根据其秩使用适当的值初始化新值实例。它对jack、queen、king和ace使用特殊的值。对于数字卡片,它使用秩的原始Int值。
BlackjackCard结构本身有两个属性—rank和suit。它还定义了一个名为description的计算属性,该属性使用存储在rank和suit中的值来构建卡片的名称和值的描述。description属性使用可选绑定检查是否有第二个值要显示,如果有,则为第二个值插入额外的描述细节。
因为BlackjackCard是一个没有自定义初始化器的结构,所以它有一个隐式的memberwise初始化器,如结构类型的memberwise初始化器中所述。您可以使用这个初始化器初始化一个名为theAceOfSpades的新常量:
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// Prints "theAceOfSpades: suit is ♠, value is 1 or 11"
尽管Rank和Suit嵌套在BlackjackCard中,但它们的类型可以从上下文推断出来,因此该实例的初始化能够通过它们的case名称(a和。黑桃)单独。在上面的例子中,description属性正确地报告黑桃a的值为1或11。
Referring to Nested Types 引用嵌套类型
若要在其定义上下文之外使用嵌套类型,请在其名称前面加上嵌套类型的名称:
let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol is "♡"
对于上面的示例,这使得Suit、Rank和值的名称能够故意保持简短,因为它们的名称自然会受到定义它们的上下文的限制。
网友评论