Spec-Zone.ru › Swift Language

Вложенные типы

Определяют типы внутри области видимости другого типа.

Перечисления часто создаются для поддержки функциональности определенного класса или структуры. Аналогично, удобно определять вспомогательные структуры только для использования в контексте более сложного типа и протоколы, которые обычно используются совместно с определенным типом. Для этого Swift позволяет определить вложенные типы, в которых вы вкладываете поддерживающие типы, такие как перечисления, структуры и протоколы, внутри определения типа, который они поддерживают.

Чтобы вложить тип в другой тип, напишите его определение внутри внешних фигурных скобок типа, который он поддерживает. Типы могут быть вложены на столько уровней, сколько требуется.

Вложенные типы в действии

В приведенном ниже примере определена структура под названием BlackjackCard, которая моделирует игральную карту, используемую в игре «Блэкджек». Структура BlackjackCard содержит два вложенных типа перечисления, называемые Suit и Rank.

В Блэкджеке карты туза имеют значение либо один, либо одиннадцать. Эта функция представлена структурой под названием 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 не используется для валетов, дам, королей и тузов.)

Как упоминалось выше, перечисление Rank определяет ещё одну вложенную структуру под названием Values. Эта структура отражает тот факт, что большинство карт имеют одно значение, но карта туза имеет два значения. Структура Values определяет две свойства для представления этого:

  • first типа Int
  • second типа Int? или «необязательное Int»

Rank также определяет вычисляемое свойство values, которое возвращает экземпляр структуры Values. Это вычисляемое свойство учитывает ранг карты и инициализирует новый экземпляр Values с соответствующими значениями на основе ее ранга. Оно использует специальные значения для jack, queen, king и ace. Для числовых карт оно использует значение исходного типа Int ранга.

Сама структура BlackjackCard имеет два свойства — rank и suit. Она также определяет вычисляемое свойство description, которое использует значения, хранящиеся в rank и suit, для создания описания имени и значения карты. Свойство description использует необязательную привязку для проверки, есть ли второе значение для отображения, и если да, вставляет дополнительные детали описания для этого второго значения.

Поскольку BlackjackCard является структурой без пользовательских инициализаторов, она имеет неявный инициализатор по членам, как описано в <doc:Initialization#Memberwise-Initializers-for-Structure-Types>. Вы можете использовать этот инициализатор для инициализации новой константы под названием 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 преднамеренно короткими, поскольку их имена естественным образом квалифицированы контекстом, в котором они определены.

This source file is part of the Swift.org open source project
Copyright © 2014 - 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API