Wymuszone rzutowanie za pomocą as! i jego zagrożenia
Używanie as! tylko wtedy, gdy rzutowanie na pewno się powiedzie.
Wymuszone rzutowanie za pomocą as! i jego zagrożenia to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.
Wymuszone rzutowanie
Operator wymuszonego rzutowania as! wykonuje rzutowanie w dół i rozpakowanie w jednym kroku. Bezpośrednio zwraca typ niebędący opcją, ale w przypadku niepowodzenia powoduje awarię.
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())Brak opakowania w opcję
W przeciwieństwie do as? wynik działania as! jest zwykłym typem, a nie opcją. Nie trzeba go rozpakowywać.
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))Ryzyko związane z as!
Jeśli instancja w rzeczywistości nie jest typu docelowego, as! powoduje błąd w czasie działania i zatrzymuje program. Nie ma możliwości odzyskania kontroli.
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")Kiedy wymuszone rzutowanie jest bezpieczne
as! należy stosować tylko wtedy, gdy ma Pan / Pani absolutną pewność co do typu, na przykład bezpośrednio po sprawdzeniu za pomocą 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())
}Wymuszone rzutowanie po gwarancji typu
Jeśli logika kodu gwarantuje dany typ, wymuszone rzutowanie dokumentuje tę pewność. Mimo to w razie wątpliwości należy preferować 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"))Porównanie as? i as!
as? jest bezpieczny i zwraca opcję, natomiast as! wymusza rzutowanie i powoduje awarię w razie niepowodzenia. Należy wybrać operator na podstawie stopnia pewności co do typu.
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())Wymuszone rzutowanie kolekcji
Wymuszone rzutowanie działa również na całych kolekcjach, na przykład array as! [Dog], ale to samo ryzyko awarii dotyczy każdego elementu.
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()) }Niebezpieczny wzorzec
Wymuszone rzutowanie tablicy zawierającej element niewłaściwego typu powoduje awarię. Dlatego w przypadku mieszanych kolekcji należy używać as? osobno dla każdego elementu.
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()) }
}Wymuszone rozpakowanie a wymuszone rzutowanie
Znak ! w as! jest koncepcyjnie podobny do wymuszonego rozpakowania opcji: jest wygodny, ale niebezpieczny, jeśli założenie okaże się błędne.
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)Najlepsza praktyka
Domyślnie należy używać as?. Operator as! należy zachować dla przypadków, w których niepowodzenie oznaczałoby błąd programisty, który powinien zostać natychmiast ujawniony podczas tworzenia programu.
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")))Przykład podsumowujący wymuszonego rzutowania
Gdy typ został zweryfikowany, as! jest czytelny. W razie wątpliwości właściwym narzędziem jest bezpieczne rzutowanie warunkowe.
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())
}Szybkie sprawdzenie
Proszę przeanalizować zagrożenia związane z wymuszonym rzutowaniem.
Podsumowanie: wymuszone rzutowanie i jego zagrożenia
Dowiedział się Pan / Dowiedziała się Pani, że as! wykonuje rzutowanie w dół i rozpakowuje wartość do typu niebędącego opcją, ale w razie niepowodzenia powoduje awarię, że należy go używać tylko wtedy, gdy typ jest pewny (często po sprawdzeniu za pomocą is), oraz że as? pozostaje bezpieczniejszym wyborem domyślnym.
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") }Często zadawane pytania
Czy lekcja „Wymuszone rzutowanie za pomocą as! i jego zagrożenia” jest bezpłatna?
Tak — pełny tekst „Wymuszone rzutowanie za pomocą as! i jego zagrożenia” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Wymuszone rzutowanie za pomocą as! i jego zagrożenia”?
Używanie as! tylko wtedy, gdy rzutowanie na pewno się powiedzie. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Swift Academy?
Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Wymuszone rzutowanie za pomocą as! i jego zagrożenia”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?
Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy rzutowania w górę i w dół
- Warunkowe rzutowanie za pomocą as?
- Wymuszone rzutowanie za pomocą as! i jego zagrożenia
- Sprawdzanie typów za pomocą is