Sobes.tech
Middle

Jaka jest różnica między protokołami a klasami, jeśli chodzi o klasy abstrakcyjne?

sobes.tech AI

Odpowiedź od AI

Protokół definiuje kontrakt: zbiór wymagań (metod, właściwości, inicjalizatorów), które musi zaimplementować typ spełniający ten protokół. Protokoły nie mają implementacji większości swoich wymagań. Nie można tworzyć instancji protokołu.

Klasa abstrakcyjna w językach innych niż Swift (np. Java) reprezentuje klasę, której nie można bezpośrednio zainstancjonować. Zawiera zarówno zaimplementowane metody (lub właściwości), jak i metody abstrakcyjne, które muszą być zaimplementowane w jej podklasach.

W Swift nie istnieje pojęcie klas abstrakcyjnych w ich tradycyjnym rozumieniu. Funkcjonalność klas abstrakcyjnych w Swift osiąga się poprzez połączenie protokołów i klas.

Używając protokołu, można zdefiniować interfejs, a następnie utworzyć zwykłą klasę, która spełnia ten protokół i zapewnia implementację. Częściowa implementacja protokołu może być dostarczona za pomocą rozszerzeń (protocol extensions), ale to nie czyni protokołu "abstrakcyjną klasą" w czystym tego słowa znaczeniu.

Protokół (Swift) Klasa abstrakcyjna (tradycyjna)
Przeznaczenie Definiowanie kontraktu (interfejsu) Definiowanie wspólnego zachowania i struktury z możliwością częściowej implementacji
Implementacja Zazwyczaj nie zawiera implementacji (z wyjątkiem rozszerzeń) Może zawierać zaimplementowane i abstrakcyjne metody
Tworzenie instancji Nie można utworzyć instancji protokołu Nie można utworzyć instancji klasy abstrakcyjnej bezpośrednio
Dziedziczenie Zgodność z protokołem (conformance) Dziedziczenie (inheritance)
Wielodziedziczenie Typ może spełniać wiele protokołów Klasa może dziedziczyć tylko po jednej klasie (w większości języków)
W Swift Jest główną formą abstrakcji Nie ma bezpośredniego odpowiednika, jest imitowane przez protokoły i klasy

Przykład imitacji klasy abstrakcyjnej za pomocą protokołu i klasy w Swift:

Protokół definiujący wymagania abstrakcyjne:

// Protokół, jako kontrakt
protocol Drawable {
    func draw()
    var color: String { get set }
}

Klasa, która spełnia protokół i zapewnia implementacje:

// Klasa implementująca protokół
class Circle: Drawable {
    var color: String

    init(color: String) {
        self.color = color
    }

    func draw() {
        print("Rysujemy koło koloru \(color)")
    }
}

Rozszerzenie zapewniające domyślną częściową implementację:

// Rozszerzenie zapewniające domyślną implementację (nie czyni protokołu klasą abstrakcyjną)
extension Drawable {
    func draw() {
        print("Rozpoczynamy rysowanie czegoś kolorem \(color)")
    }
}

W ten sposób, w Swift, protokoły odgrywają kluczową rolę w osiąganiu polimorfizmu i abstrakcji, zastępując koncepcję klas abstrakcyjnych z innych języków.