0Pricing
Swift Academy · Lezione

Casting forzato con as! e relativi rischi

Usi as! solo quando il cast è sicuramente valido.

Casting forzato con as! e relativi rischi è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. 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 4 lezioni in totale.

Casting forzato

L'operatore di casting forzato as! esegue il downcast e l'unwrapping in un unico passaggio. Restituisce direttamente il tipo non opzionale, ma causa un crash se il cast fallisce.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let dog = a as! Dog
print(dog.bark())

Nessun avvolgimento in un optional

A differenza di as?, il risultato di as! è il tipo semplice, non un optional. Non è necessario estrarre alcun valore.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let dog: Dog = a as! Dog
print(type(of: dog))

Il rischio di as!

Se l'istanza non è realmente del tipo di destinazione, as! attiva un trap a runtime e arresta il programma. Non è possibile recuperare dall'errore.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
// let cat = a as! Cat  // would crash at runtime
print("Only force-cast when certain")

Quando il casting forzato è sicuro

Usi as! solo quando ha la certezza assoluta del tipo, ad esempio subito dopo averlo verificato con is.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
if a is Dog {
    let dog = a as! Dog
    print(dog.bark())
}

Casting forzato dopo una garanzia

Se la logica del codice garantisce il tipo, un cast forzato documenta tale certezza. Se non è sicuro, preferisca comunque as?.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
func barkIfDog(_ a: Animal) {
    guard a is Dog else { return }
    let dog = a as! Dog
    print(dog.bark())
}
barkIfDog(Dog(name: "Rex"))

Confrontare as? e as!

as? è sicuro e restituisce un optional; as! è forzato e causa un crash in caso di errore. Scelga in base al livello di certezza sul tipo.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let safe = a as? Dog
let forced = a as! Dog
print(safe?.bark() ?? "nil")
print(forced.bark())

Casting forzato delle collezioni

È possibile eseguire cast forzati anche su intere collezioni, ad esempio array as! [Dog], ma lo stesso rischio di crash si applica a ogni elemento.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let animals: [Animal] = [Dog(name: "Rex"), Dog(name: "Buddy")]
let dogs = animals as! [Dog]
for d in dogs { print(d.bark()) }

Un modello pericoloso

Eseguire il casting forzato di un array che contiene un elemento errato causa un crash. Per questo, nelle collezioni miste è preferibile usare as? per ogni elemento.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let animals: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
// let dogs = animals as! [Dog] // would crash on the Cat
for a in animals {
    if let d = a as? Dog { print(d.bark()) }
}

Force unwrap e force cast

Il ! in as! è concettualmente simile al force unwrapping di un optional: è comodo, ma pericoloso se l'ipotesi è errata.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let viaOptional = (a as? Dog)!
let viaForce = a as! Dog
print(viaOptional.name, viaForce.name)

Buona pratica

Usi as? come scelta predefinita. Riservi as! ai casi in cui un fallimento indicherebbe un errore del programmatore che desidera rendere immediatamente visibile durante lo sviluppo.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
func process(_ a: Animal) -> String {
    if let d = a as? Dog { return d.bark() }
    return "not a dog"
}
print(process(Dog(name: "Rex")))
print(process(Cat(name: "Mia")))

Esempio riepilogativo di casting forzato

Quando il tipo è stato verificato, as! è chiaro e conciso. In caso di dubbio, lo strumento corretto è il cast condizionale sicuro.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let known: Animal = Dog(name: "Rex")
if known is Dog {
    print((known as! Dog).bark())
}

Controllo rapido

Ragioni sui rischi del casting forzato.

Riepilogo: casting forzato e relativi rischi

Ha imparato che as! esegue il downcast e l'unwrapping verso un tipo non opzionale, ma causa un crash in caso di errore, che dovrebbe essere usato solo quando si ha la certezza del tipo, spesso dopo una verifica con is, e che as? resta la scelta predefinita più sicura.

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
if a is Dog { print((a as! Dog).bark()) } else { print("safe skip") }

Domande Frequenti

La lezione «Casting forzato con as! e relativi rischi» è gratuita?

Sì — il testo completo di «Casting forzato con as! e relativi rischi» è 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 4 lezioni in totale.

Cosa imparerò in «Casting forzato con as! e relativi rischi»?

Usi as! solo quando il cast è sicuramente valido. 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 3 di 4.

Quanto tempo richiede la lezione «Casting forzato con as! e relativi rischi»?

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. Basi dell’upcasting e del downcasting
  2. Casting condizionale con as?
  3. Casting forzato con as! e relativi rischi
  4. Controllo dei tipi con is
← Torna a Swift Academy