Вычисляемые свойства в Swift: геттеры и сеттеры

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

Что такое вычисляемое свойство?

Прежде чем мы начнем обсуждать вычисляемые свойства, давайте для начала сделаем краткий обзор свойств:

  • Свойство связано с именем переменной или константы и является частью класса, структуры или перечисления.
  • Хранимые свойства представляют простейшую форму хранения значений в виде констант или переменных. Они имеют значение по умолчанию или получают его с помощью инициализатора.

Вычисляемое свойство вычисляет значение, а не хранит его. Вот пример:

struct Rectangle {
    var width: Double
    var height: Double
 
    var area: Double {
        width * height
    }
}

В приведенном выше коде мы создали структуру Rectangle. Она имеет два хранимых свойства width и height типа Double. Третье свойство является вычисляемым. Оно выполняет код width * height и возвращает полученное значение при вызове.

let square = Rectangle(width: 12.0, height: 12.0)
print(square.area)
// 144.0

В приведенном выше коде мы определили квадрат с шириной и высотой 12. Затем мы вычисляем площадь квадрата и выводим полученный результат в консоль.

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

Геттеры и сеттеры для вычисляемых свойств

Вычисляемые свойства могут также могут использовать геттер (get) и сеттер (set):

  • Геттер выполняется при получении значения свойства.
  • Сеттер выполняется при установке нового значения свойства.
struct User {
    private var firstName = ""
    private var lastName = ""
 
    var name: String {
        get {
            return firstName + " " + lastName
        } 
        set(newValue) {
            let split = newValue.components(separatedBy: " ")
            firstName = split[0]
            lastName = split[1]
            print("firstName = \(firstName), lastName = \(lastName)")
        }
    }
}
 
var user = User()
user.name = "John Doe"
// firstName = John, lastName = Doe
print(user.name)
// John Doe

В приведенном выше примере мы создали структуру User с двумя хранимыми свойствами firstName и lastName типа String. Третье свойство name вычисляемое.

Для вычисляемого свойства name определены методы get и метод set. Вот их синтаксис:

var property: Type {
    get {
        code
    }
    set(value) {
        code
    }
}

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

Мы можем использовать локальную константу newValue в качестве нового значения, поэтому у нас есть доступ как к новым, так и к текущим значениям. Константа newValue доступна внутри сеттера, поэтому вам не нужно объявлять ее явно. Вы можете, однако, указать собственное имя, если хотите.

set {
    // newValue - имя по умолчанию
}
set(newString) {
    // newString - созданное нами имя
}

Вычисляемые свойства только для чтения

Вычисляемое свойство только для чтения может только быть прочитано, но не изменено.

struct Circle {
    var radius: Double
    var circumference: Double {
        2 * .pi * radius
    }
}

В приведенном выше коде мы определили структуру Circle, которая имеет хранимое свойство radius и вычисляемое свойство только для чтения circumference, оба типа Double.

let earth = Circle(radius: 6371)
print(earth.circumference) 
// 40030.173592041145

Свойство circumference доступно только для чтения — оно имеет только геттер. То есть данный код аналогичен следующему:

var circumference: Double {
    get {
        return 2 * .pi * radius
    }
}

Сравнивая его с предыдущим примерами кода, мы видим два отличия:

  1. Объявление геттера удаляется. Swift понимает, что мы объявляем вычисляемое свойство только для чтения.
  2. У нас отсутствует return. Начиная с Swift 5.1 однострочные выражения могут опускать return для краткости кода.

Как можно использовать вычисляемые свойства?

Давайте посмотрим на несколько примеров использования вычисляемых свойств.

Во-первых, вычисляемое свойство только для чтения идеально подходит для краткого выражения простых вычисляемых значений. К примеру, можно вычислить окружность круга. Или вы можете получить отформатированный адрес через полученные значения.

struct Person {
    var street: String
    var streetNumber: String
    var city: String
    var postcode: String
 
    var address: String {
        "\(street) \(streetNumber)\n\(postcode), \(city)"
    }
}
 
let bob = Person(···)
print(bob.address) // Output: Московская улица, 23, 2200332, Москва

Вам не нужно хранить полный адрес, только отдельные его компоненты. Вы можете представить их так, как хотите.

Вы также можете использовать методы получения и установки вычисляемых свойств для настройки других значений, кроме самого свойства.

struct RentalCar {
    var costPerDay: Double
 
    var costPerWeek: Double {
        get {
            costPerDay * 7.0
        } set {
            costPerDay = newValue / 7.0
        }
    }
}
 
var toyota = RentalCar(costPerDay: 12.0)
toyota.costPerWeek = 100.0
print(toyota.costPerDay) // 14.28

В приведенном выше коде мы создаем структуру RentalCar которая имеет два свойства:

  • Хранимое свойство costPerDay типа Double.
  • Вычисляемое свойство costPerWeek типа Double.

Мы можем сказать, что стоимость аренды в неделю — это стоимость в день, умноженная на 7, и наоборот. В приведенном выше кодеcostPerDay является определяющим фактором для аренды автомобиля на любой срок.

Когда costPerWeek будет установлен, мы делим его на 7 и устанавливает в costPerDay. Когда мы получаем значение costPerWeek, мы умножаем его на 7 , чтобы получить стоимость за неделю.

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

Читайте также:
Добавить комментарий

Ваш адрес email не будет опубликован.