Я недавно экспериментировал с быстрыми оболочками свойств и задавался вопросом, существует ли какой-либо способ их объединения для достижения более модульной архитектуры. Например:
@WrapperOne @WrapperTwo var foo: T
Просмотр документации ничего не дал. Единственная ссылка на то, как это сделать, находится на этой странице GitHub (https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md) (цитаты ниже), которая, кажется, говорит, что это возможно. В других статьях говорилось, что их сложно составить, но не объяснялось, как это сделать. Тем не менее, я не могу понять, как это сделать, и был бы признателен, если бы кто-нибудь показал мне пример кода о том, как это реализовать (см. В нижней части поста).
Когда используются несколько оболочек свойств предусмотрены для данного свойства, обертки составлены вместе, чтобы получить оба эффекта. Например, рассмотрим состав DelayedMutable
и Copying
:
@DelayedMutable @Copying var path: UIBezierPath
Здесь у нас есть свойство, для которого мы можем отложить инициализацию до более позднего периода. Когда мы установим значение, оно будет скопировано с помощью NSCopying
метода копирования. Композиция реализуется путем вложения более поздних типов оболочек в более ранние типы оболочек, где самый внутренний вложенный тип является типом исходного свойства. В приведенном выше примере базовое хранилище будет иметь тип DelayedMutable<Copying<UIBezierPath>>
, а синтезированный метод получения / установки для пути будет просматривать оба уровня .wrappedValue:
private var _path: DelayedMutable<Copying<UIBezierPath>> = .init()
var path: UIBezierPath {
get { return _path.wrappedValue.wrappedValue }
set { _path.wrappedValue.wrappedValue = newValue }
}
Обратите внимание, что этот дизайн означает, что состав оболочки оболочки свойства не является коммутативным, поскольку порядок атрибутов влияет на способ выполнения вложения: @DelayedMutable @Copying var path1: UIBezierPath // _path1 имеет тип DelayedMutable> @Copying @DelayedMutable var path2: UIBezierPath // ошибка: _path2 имеет некорректно сформированный тип Копирование> В этом случае средство проверки типов предотвращает второе упорядочение, поскольку DelayedMutable
не соответствует протоколу NSCopying
. Это не всегда так: некоторые семантически плохие композиции не обязательно будут пойманы системой типов. Альтернативы этому подходу к композиции представлены в разделе «Рассматриваемые альтернативы».
В идеале я хотел бы реализовать что-то вроде следующего:
@propertyWrapper
struct Doubled {
var number: Int
var wrappedValue: Int {
get { (value * 2) }
set { value = Int(newValue / 2) }
}
init(wrappedValue: Int) {
self.number = wrappedValue
}
}
и
@propertyWrapper
struct Tripled {
var number: Int
var wrappedValue: Int {
get { (value * 3) }
set { value = Int(newValue / 3) }
}
init(wrappedValue: Int) {
self.number = wrappedValue
}
}
, чтобы это могло быть достигнуто:
@Tripled @Doubled var number = 5
Я понимаю, что этот пример является несколько глупой причиной для реализации композиции оболочки свойств, но это просто для простоты при изучении новой функции.
Любая помощь будет принята с благодарностью.