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

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

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

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

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

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

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

Заметка

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

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

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

В C и в Objective-C вы объявляете статические константы и переменные, связанные с типом как глобальные статические переменные. Однако в Swift, свойства типа записаны как часть определения типа, внутри его фигурных скобок, и каждое свойство ограничено областью типа, который оно поддерживает.

Чтобы объявить свойства типа, используйте ключевое слово static . Для вычисляемых свойств типа для типов класса, вы должны использовать ключевое слово class, чтобы разрешать подклассам переопределение инструкций суперкласса. Пример ниже показывает синтаксис для хранимых и вычисляемых свойств типа:

struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}

Заметка

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

Запросы и установка свойств типа

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

print(SomeStructure.storedTypeProperty)
// Выведет "Some value."
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
// Выведет "Another value."
print(SomeEnumeration.computedTypeProperty)
// Выведет "6"
print(SomeClass.computedTypeProperty)
// Выведет "27"

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

На рисунке ниже показано, как два из этих звуковых канала могут быть объединены для моделирования стерео индикатора уровня звука. Когда уровень звука канала 0, ни один из огней для этого канала не горят, но когда уровень звука 10, все огни на этом канале горят. На этом рисунке, левый канал имеет текущий уровень 9, а правый канал в настоящее время имеет уровень 7:

Аудиоканалы, описанные выше, представлены экземплярами структуры AudioChannel:

struct AudioChannel {
    static let thresholdLevel = 10
    static var maxInputLevelForAllChannels = 0
    var currentLevel: Int = 0 {
        didSet {
            if currentLevel > AudioChannel.thresholdLevel {
                // ограничиваем уровень звука максимально допустимым уровнем 
                currentLevel = AudioChannel.thresholdLevel
            }
            if currentLevel > AudioChannel.maxInputLevelForAllChannels {
                // храним значение в качестве максимального уровня 
                AudioChannel.maxInputLevelForAllChannels = currentLevel
            }
        }
    }
}

Структура AudioChannel объявляет два хранящихся свойства для поддержания функциональности. Первое - thresholdLevel определяет максимальное значение порога, которое звуковой уровень может воспроизвести. Это константное значение равное 10 для всех экземпляров AudioChannel. Если звуковой сигнал идет со значением выше чем 10, то он будет ограничен до порогового значения (как описано ниже).

Второе свойство типа - хранящееся свойство-переменная названная maxInputLevelForAllChannels. Оно отслеживает максимальное входное значение, которое было получено любым экземпляром AudioChannel. Исходное значение равно 0.

Структура AudioChannel так же определяет хранимое свойство currentLevel экземпляра, которое определяет текущий уровень аудиоканала в диапазоне от 0 до 10.

У свойства currentLevel есть обозреватель didSet для проверки значения currentLevel, всякий раз как оно присваивается. Этот наблюдатель выполняет две задачи:

  • Если новое значение currentLevel больше, чем допущено thresholdLevel, наблюдатель свойства ограничивает currentLevel до уровня thresholdLevel.
  • Если новое значение currentLevel (после возможных ограничений) больше, чем какое-либо другое, полученное экземпляром AudioChannel ранее, то наблюдатель свойства сохраняет значение нового currentLevel в статическое свойство maxInputLevelForAllChannels.

Заметка

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

Вы можете использовать структуру AudioChannel для создания двух новых аудиоканалов, названных leftChannel, rightChannel, для отображения уровней звука стерео системы:

var leftChannel = AudioChannel()
var rightChannel = AudioChannel()

Если вы установите значение leftChannel на 7, то вы увидите, что значение свойства maxInputLevelForAllChannels обновится и станет равным 7:

leftChannel.currentLevel = 7
print(leftChannel.currentLevel)
// Выведет "7"
print(AudioChannel.maxInputLevelForAllChannels)
// Выведет "7"

Если вы попробуете установить значение правого канала currentLevel равным 11, то вы можете увидеть, что значение свойства правого канала currentLevel будет ограничено максимальным значением 10, и значение свойства типа maxInputLevelForAllChannels обновится и станет равным 10:

rightChannel.currentLevel = 11
print(rightChannel.currentLevel)
// Выведет "10"
print(AudioChannel.maxInputLevelForAllChannels)
// Выведет "10"

 

Swift: 
4.0