0Pricing
Swift Academy · Lekcja

Podstawy rzutowania w górę i w dół

Przechodzenie między typami nadklas i podklas.

Podstawy rzutowania w górę i w dół to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 1 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.

Wprowadzenie do rzutowania typów

Rzutowanie typów pozwala traktować instancję jako obiekt innego typu w obrębie jego hierarchii klas. Polega na sprawdzeniu lub zmianie typu statycznego, a nie na konwersji danych.

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 d = Dog(name: "Rex")
print(d.bark())

Hierarchia klas

Rzutowanie wymaga hierarchii. W tym przypadku Dog i Cat dziedziczą po Animal. Dog jest obiektem typu Animal.

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 pet: Animal = Dog(name: "Rex")
print(pet.name)

Rzutowanie w górę za pomocą as

Rzutowanie w górę traktuje instancję podklasy jako instancję klasy bazowej. Zawsze się udaje, dlatego używa się zwykłego operatora 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" }
}
let dog = Dog(name: "Rex")
let asAnimal = dog as Animal
print(asAnimal.name)

Po co stosować rzutowanie w górę

Rzutowanie w górę jest przydatne do przechowywania różnych podklas razem, na przykład w jednej tablicy, której typ określono jako wspólną klasę bazową.

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")]
for a in zoo { print(a.name) }

Rzutowanie w górę jest zawsze bezpieczne

Ponieważ każda instancja podklasy jest również prawidłową instancją klasy bazowej, kompilator akceptuje operator as przy rzutowaniu w górę, bez ryzyka niepowodzenia.

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 cat = Cat(name: "Mia")
let animal = cat as Animal
print("Treated as Animal:", animal.name)

Utrata dostępu po rzutowaniu w górę

Po zapisaniu obiektu jako instancji typu klasy bazowej można wywoływać tylko elementy członkowskie tej klasy. Charakterystyczna dla Dog metoda bark() jest ukryta do czasu wykonania 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 a: Animal = Dog(name: "Rex")
print(a.name)
// a.bark() would not compile here

Wprowadzenie do rzutowania w dół

Rzutowanie w dół działa w przeciwnym kierunku: traktuje odwołanie do klasy bazowej jako odwołanie do konkretnej podklasy, aby ponownie uzyskać dostęp do jej elementów. Może się nie powieść, dlatego wymaga użycia as? lub 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" }
}
let a: Animal = Dog(name: "Rex")
if let dog = a as? Dog {
    print(dog.bark())
}

Dlaczego rzutowanie w dół może się nie powieść

Kompilator nie może zagwarantować, że dany obiekt Animal jest rzeczywiście obiektem typu Dog. Może być obiektem typu Cat. Ta niepewność sprawia, że rzutowanie w dół musi być sprawdzane.

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 maybeDog = a as? Dog
print("Is it a Dog?", maybeDog != nil)

Rzutowanie w dół w pętli

Typowy schemat polega na iterowaniu po tablicy typu klasy bazowej i rzutowaniu każdego elementu w dół, aby różnie obsługiwać poszczególne podklasy.

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")]
for a in zoo {
    if let dog = a as? Dog { print(dog.bark()) }
    if let cat = a as? Cat { print(cat.meow()) }
}

Podsumowanie rzutowania w górę i w dół

Rzutowanie w górę (as) prowadzi w stronę typu bazowego i zawsze się udaje. Rzutowanie w dół (as? lub as!) prowadzi w stronę konkretnego typu i może się nie powieść.

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 d = Dog(name: "Rex")
let up = d as Animal
let down = up as? Dog
print(up.name, down?.bark() ?? "no")

Rzutowanie tylko w obrębie jednej hierarchii

Można rzutować tylko między typami powiązanymi w ramach tej samej hierarchii. Typów niepowiązanych nie można rzutować na siebie nawzajem.

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")
print(a is Animal)
print(a is Dog)

Szybkie sprawdzenie

Proszę przypomnieć sobie, który kierunek rzutowania zawsze kończy się powodzeniem.

Podsumowanie: rzutowanie w górę i w dół

Dowiedział się Pan / Dowiedziała się Pani, że rzutowanie działa w obrębie hierarchii klas, że rzutowanie w górę za pomocą as w stronę typu bazowego zawsze się udaje, a rzutowanie w dół w stronę konkretnej podklasy może się nie powieść i dlatego wymaga operatorów sprawdzających przedstawionych w następnej części.

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 { print(p.name) }
}

Często zadawane pytania

Czy lekcja „Podstawy rzutowania w górę i w dół” jest bezpłatna?

Tak — pełny tekst „Podstawy rzutowania w górę i w dół” 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 „Podstawy rzutowania w górę i w dół”?

Przechodzenie między typami nadklas i podklas. Ć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 1 z 4.

Ile czasu zajmuje lekcja „Podstawy rzutowania w górę i w dół”?

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