0Pricing
Swift Academy · Lezione

Riutilizzabilità e vincoli

Progetti wrapper generici con type constraints (ad esempio Value: Comparable ), aggiunga API mirate tramite where e componga più wrapper.

Riutilizzabilità e vincoli è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 2 di 3. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 3 lezioni in totale.

Perché i vincoli?

Scriva un wrapper e lo riutilizzi con molti tipi rendendolo generico tramite i vincoli. Aggiunga API mirate con clausole where e componga piccoli wrapper.

Generico + Comparable

Utilizzi Comparable per fare in modo che un solo Bounded funzioni con Int, String e così via. I tipi non validi vengono rifiutati in fase di compilazione.

@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)

Estensioni vincolate

Utilizzi where per offrire funzionalità aggiuntive solo quando il tipo le supporta, ad esempio per flag interi o aggiornamenti in virgola mobile.

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)

Wrapper solo per collezioni

Limiti le API alle collezioni imponendo il vincolo RangeReplaceableCollection. Funziona con String e 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"]

Composizione di wrapper

Può comporre piccoli wrapper. In questo caso, Trimmed viene eseguito per primo, quindi NonEmpty garantisce un valore di fallback.

@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"

Variabili locali + riutilizzo

I wrapper funzionano anche con le variabili locali. Li mantenga generici per poterli riutilizzare tra i moduli.

@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
}

Vincolo del wrapper in fase di compilazione

Verifica rapida: come si limita un wrapper ai tipi Comparable?

Riepilogo

Riepilogo: renda i wrapper generici, aggiunga vincoli per mantenere sicuro l'utilizzo, esponga API mirate con clausole where e componga piccoli wrapper per una maggiore chiarezza.

Domande Frequenti

La lezione «Riutilizzabilità e vincoli» è gratuita?

Sì — il testo completo di «Riutilizzabilità e vincoli» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 3 lezioni in totale.

Cosa imparerò in «Riutilizzabilità e vincoli»?

Progetti wrapper generici con type constraints (ad esempio Value: Comparable ), aggiunga API mirate tramite where e componga più wrapper. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Swift Academy?

Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 3.

Quanto tempo richiede la lezione «Riutilizzabilità e vincoli»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Swift Academy?

Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Creare wrapper, projectedValue
  2. Riutilizzabilità e vincoli
  3. Pattern comuni per i wrapper (convalida, caching)
← Torna a Swift Academy