Видеокурсы по изучению языка программирования Swift. Подробнее

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

Если вы нашли опечатку в тексте, выделите ее и нажмите CTRL + ENTER.

Пример ниже определяет структуру BlackjackCard, которая создает модель игральных карт игры Blackjack. Структура BlackjackCard содержит два вложенных перечисления типов Suit, Rank.

В игре Blackjack карта Ace (Туз) имеет значение либо один, либо одиннадцать. Это особенность отображается структурой 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 не используется для карт Jack, Queen, King, Ace или по-русски Валета, Королевы, Короля и Туза).

Как уже упоминалось ранее, структура 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 является структурой без пользовательских инициализаторов, она имеет неявный почленный инициализатор, что описано в главе “Почленная инициализация структурных типов”. Вы можете использовать этот инициализатор для инициализации новой константы theAceOfSpades:

let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// Выведет "theAceOfSpades: suit is ♠, value is 1 or 11"

Даже если Rank и Suit являются вложенными в BlackjackCard, их типы могут наследоваться из контекста, таким образом инициализация этого экземпляра может сослаться на члены перечисления по их именам (.ace и .spades). В примере выше свойство description корректно отображает то, что Туз (Ace) масти пики (Spades) имеет значение либо 1, либо 11.

 

Swift: 
4.0