Свойства в Swift

Свойства Swift связывают значения с определённым классом, структурой или перечислением.

Свойства можно разделить на хранимые свойства и вычисляемые свойства:

Хранимые свойства Вычисляемые свойства
Хранить константы или переменные как часть экземпляра Вычислять значение (а не хранить его)
Используется для классов и структур Используется для классов, структур и перечислений

Хранимые и вычисляемые свойства обычно используются для экземпляров определённого типа.

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

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


Хранимые свойства

Проще говоря, хранимое свойство — это константа или переменная, хранящаяся в экземпляре определённого класса или структуры.

Хранимые свойства могут быть переменными хранимыми свойствами (определяемыми с помощью ключевого слова `var`) или константными хранимыми свойствами (определяемыми с помощью ключевого слова `let`).

  • Можно указать значение по умолчанию при определении хранимого свойства.

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

import Cocoa

struct Number
{
   var digits: Int
   let pi = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.pi)")

Вывод вышеприведённой программы:

67
3.1415

Рассмотрим следующий код:

let pi = 3.1415

В коде `pi` получает значение по умолчанию при определении хранимого свойства (`pi = 3.1415`), поэтому независимо от того, когда вы создаёте экземпляр структуры, оно не изменится.

Если вы определите константное хранимое свойство и попытаетесь его изменить, будет выдана ошибка, как показано ниже:

import Cocoa

struct Number
{
    var digits: Int
    let numbers = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

Вышеприведённая программа при выполнении выдаст ошибку, как показано ниже:

error: cannot assign to property: 'numbers' is a 'let' constant
n.numbers = 8.7

Это означает, что 'numbers' является константой, и вы не можете её изменить.


Ленивые хранимые свойства

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

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

Примечание:
Вы должны объявить ленивое хранимое свойство как переменную (с использованиемvarключевого слова), потому что значение свойства может быть не получено до завершения инициализации экземпляра. Константные свойства должны иметь начальное значение до завершения инициализации, поэтому они не могут быть объявлены как ленивые свойства.

Ленивые хранимые свойства обычно используются для:

  • Отложенного создания объектов.

  • Когда значение свойства зависит от других неизвестных классов.

import Cocoa

class sample {
    lazy var no = number() // `var` 关键字是必须的
}

class number {
    var name = "Example Swift 教程"
}

var firstsample = sample()
print(firstsample.no.name)

Вывод вышеприведённой программы:

Example Swift 教程

Переменные экземпляра

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

Язык программирования Swift объединяет эти концепции с помощью свойств. Свойства в Swift не имеют соответствующей переменной экземпляра, и к внутреннему хранилищу свойства нельзя обратиться напрямую. Это позволяет избежать путаницы с разными способами доступа в разных сценариях, а также упрощает определение свойства до одной инструкции.

Вся информация о свойстве в типе — включая его имя, тип и характеристики управления памятью — определяется в одном-единственном месте (в определении типа).


Вычисляемые свойства

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

import Cocoa

class sample {
    var no1 = 0.0, no2 = 0.0
    var length = 300.0, breadth = 150.0
    
    var middle: (Double, Double) {
        get{
            return (length / 2, breadth / 2)
        }
        set(axis){
            no1 = axis.0 - (length / 2)
            no2 = axis.1 - (breadth / 2)
        }
    }
}

var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)

print(result.no1)
print(result.no2)

Вывод вышеприведённой программы:

(150.0, 75.0)
-150.0
-65.0

Если сеттер вычисляемого свойства не определяет имя параметра для нового значения, можно использовать имя по умолчанию `newValue`.


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

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

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

import Cocoa

class film {
    var head = ""
    var duration = 0.0
    var metaInfo: [String:String] {
        return [
            "head": self.head,
            "duration":"\(self.duration)"
        ]
    }
}

var movie = film()
movie.head = "Swift 属性"
movie.duration = 3.09

print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

Вывод вышеприведённой программы:

Swift 属性
3.09

Примечание:

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


Наблюдатели свойств

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

Наблюдатели свойств можно добавлять к хранимым свойствам, кроме ленивых хранимых свойств, а также можно добавлять наблюдатели свойств к наследуемым свойствам (включая хранимые и вычисляемые свойства), переопределяя свойство.

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

К свойству можно добавить один или все из следующих наблюдателей:

  • willSetвызывается перед установкой нового значения
  • didSetвызывается сразу после установки нового значения
  • Наблюдатели `willSet` и `didSet` не вызываются во время инициализации свойства.
import Cocoa

class Samplepgm {
    var counter: Int = 0{
        willSet(newTotal){
            print("计数器: \(newTotal)")
        }
        didSet{
            if counter > oldValue {
                print("新增数 \(counter - oldValue)")
            }
        }
    }
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Вывод вышеприведённой программы:

计数器: 100
新增数 100
计数器: 800
新增数 700

Глобальные и локальные переменные

Описанные для вычисляемых свойств и наблюдателей свойств шаблоны можно также применять к глобальным и локальным переменным.

Локальные переменные Глобальные переменные
Переменные, определённые внутри функции, метода или замыкания. Переменные, определённые вне функций, методов, замыканий или любого типа.
Используются для хранения и извлечения значений. Используются для хранения и извлечения значений.
Хранимые свойства используются для получения и установки значений. Хранимые свойства используются для получения и установки значений.
Также используется для вычисляемых свойств. Также используется для вычисляемых свойств.

Свойства типа

Свойства типа записываются как часть определения типа, внутри самых внешних фигурных скобок ({}) типа.

Используйте ключевое слово `static` для определения свойств типа для типов значений, а ключевое слово `class` — для определения свойств типа для классов.

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

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


Получение и установка значений свойств типа

Как и в случае со свойствами экземпляра, доступ к свойствам типа осуществляется с помощью оператора точки (.). Однако доступ к свойствам типа и их установка происходят через сам тип, а не через экземпляр. Например:

import Cocoa

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}

var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()

stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks) 

stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

Вывод вышеприведённой программы:

97
87
Другие расширения