Nested Types (嵌套类型)

Enumerations are often created to support a specific class or structure’s functionality. Similarly, it can be convenient to define utility classes and structures purely for use within the context of a more complex type. To accomplish this, Swift enables you to definenested types, whereby you nest supporting enumerations, classes, and structures within the definition of the type they support.

枚举常被用于为特定类或结构体实现某些功能。类似的,枚举可以方便的定义工具类或结构体,从而为某个复杂的类型所使用。为了实现这种功能,Swift 允许你定义嵌套类型,可以在支持的类型中定义嵌套的枚举、类和结构体。

To nest a type within another type, write its definition within the outer braces of the type it supports. Types can be nested to as many levels as are required.

要在一个类型中嵌套另一个类型,将嵌套类型的定义写在其外部类型的{}内,而且可以根据需要定义多级嵌套。

Nested Types in Action (嵌套类型实践)

The example below defines a structure calledBlackjackCard, which models a playing card as used in the game of Blackjack. TheBlackJackstructure contains two nested enumeration types calledSuitandRank.

下面这个例子定义了一个结构体BlackjackCard(二十一点),用来模拟BlackjackCard中的扑克牌点数。BlackjackCard结构体包含两个嵌套定义的枚举类型Suit和Rank。

In Blackjack, the Ace cards have a value of either one or eleven. This feature is represented by a structure calledValues, which is nested within theRankenumeration:

在BlackjackCard中,Ace牌可以表示1或者11,Ace牌的这一特征通过一个嵌套在Rank枚举中的结构体Values来表示:

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:

           returnValues(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

}

}

TheSuitenumeration describes the four common playing card suits, together with a rawCharactervalue to represent their symbol.

Suit枚举用来描述扑克牌的四种花色,并用一个Character类型的原始值表示花色符号。

TheRankenumeration describes the thirteen possible playing card ranks, together with a rawIntvalue to represent their face value. (This rawIntvalue is not used for the Jack, Queen, King, and Ace cards.)

Rank枚举用来描述扑克牌从Ace~10,以及J、Q、K,这13种牌,并用一个Int类型的原始值表示牌的面值。(这个Int类型的原始值未用于Ace、J、Q、K这4种牌。)

As mentioned above, theRankenumeration defines a further nested structure of its own, calledValues. This structure encapsulates the fact that most cards have one value, but the Ace card has two values. TheValuesstructure defines two properties to represent this:

如上所述,Rank枚举在内部定义了一个嵌套结构体Values。结构体Values中定义了两个属性,用于反映只有Ace有两个数值,其余牌都只有一个数值:

first, of typeInt

second, of typeInt?, or “optionalInt”

Rankalso defines a computed property,values, which returns an instance of theValuesstructure. This computed property considers the rank of the card and initializes a newValuesinstance with appropriate values based on its rank. It uses special values forjack,queen,king, andace. For the numeric cards, it uses the rank’s rawIntvalue.

Rank还定义了一个计算型属性values,它将会返回一个Values结构体的实例。这个计算型属性会根据牌的面值,用适当的数值去初始化Values实例。对于J、Q、K、Ace这四种牌,会使用特殊数值。对于数字面值的牌,使用枚举实例的原始值。

TheBlackjackCardstructure itself has two properties—rankandsuit. It also defines a computed property calleddescription, which uses the values stored inrankandsuitto build a description of the name and value of the card. Thedescriptionproperty uses optional binding to check whether there is a second value to display, and if so, inserts additional description detail for that second value.

BlackjackCard结构体拥有两个属性——rank与suit。它也同样定义了一个计算型属性description,description属性用rank和suit中的内容来构建对扑克牌名字和数值的描述。该属性使用可选绑定来检查可选类型second是否有值,若有值,则在原有的描述中增加对second的描述。

BecauseBlackjackCardis a structure with no custom initializers, it has an implicit memberwise initializer, as described inMemberwise Initializers for Structure Types. You can use this initializer to initialize a new constant calledtheAceOfSpades:

因为BlackjackCard是一个没有自定义构造器的结构体,在结构体的逐一成员构造器中可知,结构体有默认的成员构造器,所以你可以用默认的构造器去初始化新常量theAceOfSpades:

let theAceOfSpades=BlackjackCard(rank: .ace,suit: .spades)

print("theAceOfSpades:\(theAceOfSpades.description)")

// Prints "theAceOfSpades: suit is ♠, value is 1 or 11"

Even thoughRankandSuitare nested withinBlackjackCard, their type can be inferred from context, and so the initialization of this instance is able to refer to the enumeration cases by their case names (.aceand.spades) alone. In the example above, thedescriptionproperty correctly reports that the Ace of Spades has a value of1or11.

尽管Rank和Suit嵌套在BlackjackCard中,但它们的类型仍可从上下文中推断出来,所以在初始化实例时能够单独通过成员名称(.Ace和.Spades)引用枚举实例。在上面的例子中,description属性正确地反映了黑桃A牌具有1和11两个值。

Referring to Nested Types (引用嵌套类型)

To use a nested type outside of its definition context, prefix its name with the name of the type it is nested within:

在外部引用嵌套类型时,在嵌套类型的类型名前加上其外部类型的类型名作为前缀:

let heartsSymbol=BlackjackCard.Suit.hearts.rawValue

// heartsSymbol is "♡"

For the example above, this enables the names ofSuit,Rank, andValuesto be kept deliberately short, because their names are naturally qualified by the context in which they are defined.

对于上面这个例子,这样可以使Suit、Rank和Values的名字尽可能的短,因为它们的名字可以由定义它们的上下文来限定。

你可能感兴趣的:(Nested Types (嵌套类型))