Ciekawostki #1: Konstrukcja niebezpośrednia

Nauka programownia

Opublikowany: Sep 18, 2018

Popatrzmy na konstrukcję obiektów w Swift trochę odwrotnie. Jeśli znacie narzędzie JSONDecoder(), to na pewno widzieliście wywołanie typu

let decoder = JSONDecoder()
let product = try decoder.decode(A.self, from: json)

Na podstawie typu przekazanego jako parametr, funkcja decodekonstruuje instancję obiektu/struktury typu A. jednak nie widać tu bezpośredniego wywołania konstruktora typu.

let a = A()

Jak więc jest to zrealizowane? Spróbujmy napisać własny przykład, w którym stworzymy funkcję fabrykującą obiekty pewnego typu.

W funkcji decode z klasy JSONDecoder wymagane jest, aby podany typ był zgodny z protokołem Codable. Zrobimy coś podobnego. Potrzebujemy protokołu, który pozwoli zagwarantować, że wykorzystane typy będą pozwalały na konstrukcję ich obiektów. Protokół Initializablebedzie więc wymagać istnienia funkcji init().

protocol Initializable {
    init()
}

Mając tak zdefiniowany protokoł możemy przejść do implementacji funkcji fabrykującej. Skorzystamy z notacji <> pozwalającej na stworzenie funkcji generycznej.

func createInstance<T>(typeThing:T.Type) -> T where T:Initializable{
    return typeThing.init()
}

Funkcja createInstance jest więc sparametryzowana typem , który jest dedukowany z przekazanego parametru (T.Type). Zwracany jest obiekt typu T. Na końcu nagłówka funkcji możemy zobaczyć, że typ Tmusi implementować nasz protokoł (where T:Initializable).

Dzięki temu jesteśmy pewni, że typ implementuje funkcję init(), a zatem poprawna będzie instrukcja return typeThing.init(). W przypadku metatypów nie można użyć zwykłej notacji typeThing()tylko trzeba jawnie określić wywołanie konkretnego konstruktora.

Konstrukcja obiektu dowolnego typu spełniającego określone warunki będzie więc wymagała użycia:

let a = createInstance(typeThing: SomeTestType.self)

Oczywiście pozostał jeszcze do zdefiniowania sam typ SomeTestType, który będąc zgodnym z protokołem Initializablemusi implementować konstruktor init().

class SomeTestType : Initializable {
    var property:String
    required init() {
        property = "It works!"
    }

}

Gotowe.


Image
Programowanie Swift
Swift on Windows
Sep 23, 2020
Image
Felieton
Zarabianie Schrodingera
Sep 03, 2019
Image
Felieton
Rozliczanie aplikacji sprzedanych w AppStore
Jun 10, 2019
Image
Felieton
Cały internet na płycie CD
Apr 01, 2019
Image
Nauka programownia
Swift: O co chodzi z tymi kolejkami?
Feb 17, 2019

Nasze szkolenia