Повторное использование и ограничения
Проектируйте обобщённые обёртки с ограничениями типов (например, Value: Comparable ), добавляйте специализированные API с помощью where и объединяйте несколько обёрток.
«Повторное использование и ограничения» — бесплатный урок Swift Academy на CoddyKit. Это урок 2 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 3 уроков всего.
Зачем нужны ограничения?
Напишите одну обёртку и повторно используйте её для множества типов, сделав её обобщённой с помощью ограничений. Добавляйте специализированные API с предложениями where и объединяйте небольшие обёртки.
Обобщённость + Comparable
Используйте Comparable, чтобы одна Bounded работала с Int, String и другими типами. Недопустимые типы отклоняются во время компиляции.
@propertyWrapper
struct Bounded<Value: Comparable> {
private var value: Value
private let range: ClosedRange<Value>
var wrappedValue: Value {
get { value }
set {
// clamp using Comparable
if newValue < range.lowerBound { value = range.lowerBound }
else if newValue > range.upperBound { value = range.upperBound }
else { value = newValue }
}
}
init(wrappedValue: Value, _ range: ClosedRange<Value>) {
self.range = range
self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
}
struct Stats {
@Bounded(0...100) var score: Int = 120
@Bounded("a"..."z") var letter: String = "Swift"
}
var st = Stats()
print(st.score) // 100
st.letter = "m"
print(st.letter)Ограниченные расширения
Используйте where, чтобы предлагать дополнительные возможности только тогда, когда тип их поддерживает, например целочисленные флаги или операции с плавающей точкой.
extension Bounded where Value: BinaryInteger {
var isMaxed: Bool { wrappedValue == range.upperBound }
}
extension Bounded where Value: FloatingPoint {
mutating func bump(by delta: Value) { wrappedValue = wrappedValue + delta }
}
struct Meter {
@Bounded(0...10) var steps: Int = 9
@Bounded(0.0...1.0) var progress: Double = 0.25
}
var m = Meter()
print(m.$steps) // projectedValue not defined; accessing wrapper is not allowed directly here
print(m._steps) // compiler creates backing storage name; shown for illustration only
print(m.steps) // 9
print(m._progress) // backing storage (illustrative)
m._progress.bump(by: 0.6)
print(m.progress) // 0.85 (clamped if exceeded)Обёртка только для коллекций
Ограничьте API коллекциями, добавив ограничение на RangeReplaceableCollection. Это работает со String и Array.
@propertyWrapper
struct MaxLength<Value: RangeReplaceableCollection> where Value.Element: Sendable {
private var storage: Value
private let limit: Int
var wrappedValue: Value {
get { storage }
set {
var v = newValue
if v.count > limit { v.removeLast(v.count - limit) }
storage = v
}
}
init(wrappedValue: Value, _ limit: Int) {
self.limit = limit
self.storage = wrappedValue
if storage.count > limit { storage.removeLast(storage.count - limit) }
}
}
struct Post {
@MaxLength(10) var title: String = "hello swift learners"
@MaxLength(5) var tags: [String] = ["swift","ios","spm"]
}
var p = Post()
print(p.title) // "hello swif"
print(p.tags) // ["swift","ios","spm"]Композиция обёрток
Можно объединять небольшие обёртки. Здесь сначала выполняется Trimmed, а затем NonEmpty обеспечивает запасное значение.
@propertyWrapper
struct Trimmed {
private var s: String = ""
var wrappedValue: String {
get { s }
set { s = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
}
init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}
@propertyWrapper
struct NonEmpty {
private var s: String = ""
var wrappedValue: String {
get { s }
set { s = newValue.isEmpty ? "N/A" : newValue }
}
init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}
struct Profile {
@NonEmpty @Trimmed var displayName: String = " "
}
var prof = Profile()
print(prof.displayName) // "N/A"Локальные переменные и повторное использование
Обёртки также работают с локальными переменными. Делайте их обобщёнными, чтобы повторно использовать их в разных модулях.
@propertyWrapper
struct Default<Value> {
private var value: Value
private let make: () -> Value
var wrappedValue: Value {
get { value }
set { value = newValue }
}
init(wrappedValue: Value, _ factory: @escaping () -> Value) {
self.value = wrappedValue
self.make = factory
}
mutating func reset() { value = make() }
}
// Local variable usage
do {
@Default({ 0 }) var counter: Int = 5
print(counter) // 5
_counter.reset()
print(counter) // 0
}Ограничение обёртки на этапе компиляции
Быстрая проверка: как ограничить обёртку типами Comparable?
Итоги
Итоги: делайте обёртки обобщёнными, добавляйте ограничения для безопасного использования, открывайте специализированные API с предложениями where и объединяйте небольшие обёртки для ясности.
Часто задаваемые вопросы
Урок «Повторное использование и ограничения» бесплатный?
Да — полный текст урока «Повторное использование и ограничения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 3 уроков всего.
Чему я научусь в уроке «Повторное использование и ограничения»?
Проектируйте обобщённые обёртки с ограничениями типов (например, Value: Comparable ), добавляйте специализированные API с помощью where и объединяйте несколько обёрток. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 3.
Сколько времени занимает урок «Повторное использование и ограничения»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Создание обёрток, projectedValue
- Повторное использование и ограничения
- Распространённые шаблоны обёрток (проверка, кэширование)