Swift 5.x - 嵌套类型(中文文档)

1,699 阅读4分钟

引言

继续学习Swift文档,从上一章节:类型转换,我们学习了Swift类型转换相关的内容,主要有使用is进行类型检查、as?as!进行向下转型的类型转换语法、Any和AnyObject的类型转换等这些内容。现在,我们学习Swift嵌套类型的相关内容。由于篇幅较长,这里分篇来记录,接下来,开始吧!

嵌套类型

枚举通常是为了支持特定类或结构体的功能而创建的。类似地,定义实用程序类和结构体纯粹是为了在更复杂的类型的上下文中使用,这可能会很方便。为了实现这一点,Swift允许您定义嵌套类型,从而在它们支持的类型的定义中嵌套支持枚举、类和结构体。

若要在另一个类型中嵌套一个类型,请在其支持的类型的外部大括号中编写其定义。类型可以嵌套到所需的任意级别。

1 操作中的嵌套类型

下面的示例定义了一个名为BlackjackCard的结构体,它为21点游戏中使用的扑克牌建模。BlackjackCard结构体包含两个嵌套的枚举类型Suit和Rank。 在21点中,王牌的值为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枚举描述了13个可能的扑克牌等级,以及表示其面值的原始Int值。(此原始Int值不用于Jack、Queen、King和Ace卡。) 如上所述,Rank枚举定义了自己的另一个嵌套结构体,称为Values。这个结构封体装了这样一个事实:大多数卡只有一个值,而Ace卡有两个值。Values结构体定义了两个属性来表示这一点:

  • first, of type Int
  • second, of type Int?, or “optional Int”

Rank还定义了一个计算属性values,它返回values结构体的一个实例。此计算属性考虑卡的等级,并根据卡的等级使用适当的值初始化新的值实例。它对jack、queen、king和ace使用特殊值。对于数字卡,它使用raw的原始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中,它们的类型也可以从上下文中推断出来,因此这个实例的初始化能够仅通过它们的case名称(.ace和.spades)来引用枚举cases。在上面的示例中,description属性正确地报告了黑桃的Ace的值为1或11。

2 引用嵌套类型

要在其定义上下文之外使用嵌套类型,请在其名称前面加上嵌套在其中的类型的名称:

let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol is "♡"

对于上面的例子,这使得Suit、Rank和Values的名称保持简短,因为它们的名称是由定义它们的上下文自然限定的。

上一章节:类型转换 下一章节:扩展

参考文档:Swift - Nested Types