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

Перечисления и структуры

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

Используйте оператор enum для создания перечислений. Подобно классам и другим именованным типам, перечисления могут иметь методы связанные с ним.

enum Rank: Int {
    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king
    func simpleDescription() -> String {
        switch self {
        case .ace:
            return "ace"
        case .jack:
            return "jack"
        case .queen:
            return "queen"
        case .king:
            return "king"
        default:
            return String(self.rawValue)
        }
    }
}
let ace = Rank.ace
let aceRawValue = ace.rawValue

Задание

Напишите функцию, сравнивающую два Rank значения, с помощью сравнения их исходных (raw) значений.

По умолчанию Swift присваивает исходные значения, начиная с нуля и увеличивая их на единицу каждый раз, но вы можете изменить это поведение, явно указав значения. В приведенном выше примере, Ace явно присвоено исходное значение 1, остальные исходные значения присваиваются по порядку. Вы также можете использовать строки или числа с плавающей точкой в качестве типа исходного значения перечисления. Используйте свойство rawValue для доступа к исходному значению элемента перечисления.

Используйте инициализатор init?(rawValue:) для того, чтобы создать экземпляр перечисления из исходного значения:

if let convertedRank = Rank(rawValue: 3) {
    let threeDescription = convertedRank.simpleDescription()
}

Значения элементов перечисления - это реальные значения, а не просто еще один способ написания исходных значений. Фактически, в тех случаях, когда нет ясного представления об исходном значении, вы можете их не писать.

enum Suit {
    case spades, hearts, diamonds, clubs
    func simpleDescription() -> String {
        switch self {
        case .spades:
            return "spades"
        case .hearts:
            return "hearts"
        case .diamonds:
            return "diamonds"
        case .clubs:
            return "clubs"
        }
    }
}
let hearts = Suit.hearts
let heartsDescription = hearts.simpleDescription()

Задание

Добавьте метод color() для Suit, который возвращает "black" для spades (пики) и clubs (трефы), и возвращает "red" для hearts (червы) и diamonds (бубны).

Обратите внимание на два способа обращения к элементам перечисления Hearts выше. Во время присвоения значения константе hearts, обращение к элементу перечисления Suit.hearts происходит через его полное имя, потому что константа не имеет явно указанного типа. Внутри switch, обращение к перечислению происходит через сокращённую форму .hearts, потому что значение self уже известно, и оно Suit. Вы можете использовать сокращенную форму каждый раз, когда тип значения известен.

Используйте оператор struct для создания структур. Структуры поддерживают многие характерные черты классов, в том числе методы и инициализаторы. Одно из наиболее важных различий между классами и структурами в том, что структуры всегда копируются когда они передаются в коде, а классы, передаются по ссылке.

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

Задание

Добавьте метод для Card, который бы создал полную колоду карт, с одной картой из каждой комбинации ранга (rank) и масти (suit).

Экземпляр элемента перечисления может иметь значения, связанные с экземпляром. Экземпляры одинаковых элементов перечисления могут иметь разные значения, связанные с ним. Вы указываете связанные значения, когда создаете экземпляр. Связанные значения и исходные значения - это разные понятия. Исходное значение элемента перечисления одно и то же для всех экземпляров, вы указываете исходное значение, когда объявляете перечисление.

Например, рассмотрим случай с запросом времени восхода и заката солнца у сервера. Сервер, либо возвращает информацию, либо возвращает ошибку.

enum ServerResponse {
    case result(String, String)
    case failure(String)
}
 
let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")
 
switch success {
case let .result(sunrise, sunset):
    print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
    print("Failure...  \(message)")
}

Задание

Добавьте третий случай case в ServerResponse и в switch.

Обратите внимание, как время восхода (sunrise) и заката (sunset) извлекаются из значения ServerResponse, так же как значение для части поиска совпадений в блоках case у switch.

 

Swift: 
3.0