Swift Academy · Lekcja

Warunkowe rzutowanie za pomocą as?

Próba rzutowania zwracającego optional w razie niepowodzenia.

Lekcja 2 z 413 kroki

Warunkowe rzutowanie za pomocą as? to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 2 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.

Rzutowanie warunkowe

Operator rzutowania warunkowego as? próbuje wykonać rzutowanie w dół i zwraca opcję: opakowaną wartość, jeśli operacja się powiedzie, albo nil, jeśli się nie powiedzie.

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 maybe = a as? Dog
print(maybe != nil)

Wynik jest opcją

Ponieważ rzutowanie może się nie powieść, typem wyniku jest Dog?, a nie Dog. Przed użyciem należy rozpakować opcję.

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 maybe: Dog? = a as? Dog
print(type(of: maybe))

Rozpakowywanie za pomocą if let

Idiomatycznym sposobem użycia as? jest umieszczenie go w wiązaniu if let, którego ciało zostanie wykonane tylko wtedy, gdy rzutowanie się powiedzie.

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 let dog = a as? Dog {
    print(dog.bark())
} else {
    print("Not a dog")
}

Nieudane rzutowanie zwraca nil

Jeśli instancja nie jest typu docelowego, as? zwraca nil, a ciało if let zostaje pominięte.

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 = Cat(name: "Mia")
if let dog = a as? Dog {
    print(dog.bark())
} else {
    print("That is not a dog")
}

Łączenie z guard let

Można również użyć guard let, aby wykonać rzutowanie na początku i zakończyć działanie, jeśli się ono nie powiedzie. Dzięki temu główna ścieżka kodu nie wymaga dodatkowego wcięcia.

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 describe(_ a: Animal) {
    guard let cat = a as? Cat else {
        print("Not a cat")
        return
    }
    print(cat.meow())
}
describe(Cat(name: "Mia"))
describe(Dog(name: "Rex"))

Rzutowanie warunkowe w pętlach

Iterowanie po mieszanej tablicy i warunkowe rzutowanie każdego elementu to przejrzysty sposób bezpiecznej obsługi różnych podklas.

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 zoo: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia"), Dog(name: "Buddy")]
for a in zoo {
    if let dog = a as? Dog {
        print(dog.bark())
    }
}

Rzutowanie do protokołów

as? sprawdza również zgodność z protokołem: zwraca wartość, jeśli instancja jest zgodna z protokołem, a w przeciwnym razie nil.

protocol Greeter { func greet() -> String }
class Person: Greeter { func greet() -> String { return "Hi" } }
class Rock {}
let items: [Any] = [Person(), Rock()]
for item in items {
    if let g = item as? Greeter { print(g.greet()) }
}

Operator ?? po rzutowaniu

Operator as? można połączyć z operatorem ??, aby podać wartość zastępczą, gdy rzutowanie się nie powiedzie.

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 = Cat(name: "Mia")
let sound = (a as? Dog)?.bark() ?? "unknown sound"
print(sound)

Łączenie wywołań metod po rzutowaniu

Łańcuchowe wywołania opcjonalne pozwalają wywołać metodę na wyniku rzutowania; całe wyrażenie ma wartość nil, jeśli rzutowanie się nie powiedzie.

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 bark = (a as? Dog)?.bark()
print(bark as Any)

Dlaczego preferuje się rzutowanie warunkowe

as? nigdy nie powoduje awarii; nieudane rzutowanie po prostu daje nil. Dzięki temu jest bezpieślnym wyborem domyślnym przy rzutowaniu w dół.

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 unknown: Animal = Cat(name: "Mia")
let result = unknown as? Dog
print("Crashes? No. Value is nil:", result == nil)

Przykład podsumowujący rzutowania warunkowego

Łącząc wszystkie elementy: należy bezpiecznie wykryć podtyp, wykonać na nim odpowiednią operację, a w przeciwnym razie łagodnie obsłużyć sytuację zastępczą.

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 sound(of a: Animal) -> String {
    if let d = a as? Dog { return d.bark() }
    if let c = a as? Cat { return c.meow() }
    return "silence"
}
print(sound(of: Dog(name: "Rex")))
print(sound(of: Cat(name: "Mia")))

Szybkie sprawdzenie

Proszę przypomnieć sobie typ wyniku rzutowania warunkowego.

Podsumowanie: rzutowanie warunkowe za pomocą as?

Dowiedział się Pan / Dowiedziała się Pani, że as? wykonuje bezpieczne rzutowanie w dół i zwraca opcję, że if let i guard let rozpakowują pomyślnie uzyskaną wartość, a także że operator ten nigdy nie powoduje awarii, ponieważ niepowodzenie zwraca po prostu nil, dzięki czemu jest preferowanym operatorem rzutowania w dół.

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 pets: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for p in pets {
    if let d = p as? Dog { print(d.bark()) } else if let c = p as? Cat { print(c.meow()) }
}
Bezpłatny start

Ucz się Swift dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
122
Lekcje
409

Często zadawane pytania

Czy lekcja „Warunkowe rzutowanie za pomocą as?” jest bezpłatna?

Tak — pełny tekst „Warunkowe rzutowanie za pomocą as?” 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 „Warunkowe rzutowanie za pomocą as?”?

Próba rzutowania zwracającego optional w razie niepowodzenia. Ć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 2 z 4.

Ile czasu zajmuje lekcja „Warunkowe rzutowanie za pomocą as?”?

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

  1. Podstawy rzutowania w górę i w dół
  2. Warunkowe rzutowanie za pomocą as?
  3. Wymuszone rzutowanie za pomocą as! i jego zagrożenia
  4. Sprawdzanie typów za pomocą is
← Powrót do Swift Academy