Jason. Cała informatyka w jednym miejscu!

Po pierwszym poruszeniu tematu typów generycznych, zapraszam na drugą część opisującą jak tworzona jest funkcja sparametryzowana w języku Kotlin! Zaprezentuję dwa przypadki: kiedy funkcja jest częścią klasy oraz kiedy funkcjonuje niezależnie od jakiejkolwiek (na zewnątrz).

FUNKCJA SPARAMETRYZOWANA W JĘZYKU KOTLIN W DWÓCH WARIANTACH

Zanim rozpoczniemy teorię, poproszę Was o zajrzenie do poprzedniej części, gdyż streszczam w niej do czego w ogóle służą typy generyczne.

Zaczniemy od prostego tłumaczenia. Gdy mowa o funkcji sparametryzowanej, to chodzi o funkcję dysponującą parametrem typu, na przykład T. Czy ten T jest parametrem funkcji, czy jest on wartością wynikową funkcji, w obu tych przypadkach mamy tu ewidentnie do czynienia z funkcją sparametryzowaną, czyli funkcją wykorzystującą typ generyczny. W zależności od jej umiejscowienia w kodzie (na zewnątrz lub w klasie), istnieją takie dwa szablony deklaracji, które możecie spotkać podczas przeglądania cudzych kodów źródłowych. Czyli jak możecie rozpoznać, że to funkcja sparametryzowana w języku Kotlin.

FUNKCJA NA ZEWNĄTRZ

Przyjrzyjmy się najpierw budowie takiej funkcji sparametryzowanej na zewnątrz klasy albo jeszcze inaczej, bez żadnych ułatwień składniowych. Oto struktura:

fun <T> doSomething(t: T)

Co najbardziej może przykuwać uwagę? Nietypowe miejsce określenia parametru typu. Te same nawiasy kątowe, tylko umieszczone zaraz po słowie kluczowym "fun"! Dlaczego akurat w tym miejscu? Bo później jest lista parametrów, która musi mieć informacje o ewentualnych ograniczeniach, bądź modyfikatorach parametru typu T. Najprościej pisząc, jedno musi być wcześniej od drugiego.

Co w przypadku większej liczby takich parametrów generycznych? Wtedy funkcja sparametryzowana w języku Kotlin ma wyglądać następująco:

fun <T, U, V> doSomething(t: T, u: U, v: V)

Gdyby którykolwiek z nich miał posiadać ograniczenie "bycia" konkretną klasą albo jej pochodną, stosujemy taki sam manewr jak poprzednio:

fun <T, U, V : Point> doSomething(t: T, u: U, v: V)

Więcej dodawać na chwilę obecną nie potrzeba.

FUNKCJA W KLASIE

A co, gdy funkcja sparametryzowana w języku Kotlin może skorzystać z parametru typu będącego w nagłówku klasy? Mamy o wiele łatwiejszą sprawę:

class Generic<T : Point>(val t: T) {
	fun doSomething(t: T) {
		
	}
}

Po prostu bez ściemy, ignorujemy nawiasy kątowe po słowie "fun", dalej pisząc wszystko tak samo, gdyż ten sam T został już określony wewnątrz nawiasów kątowych umieszczonych obok nazwy klasy.

Dodam, że nic nie stoi na przeszkodzie, żeby funkcja sparametryzowana w języku Kotlin posiadała te same nawiasy będąc nadal częścią klasy, jeśli pragniemy zdefiniować osobny parametr typu np. o literce U. Konkretnie mam na myśli to:

class Generic<T : Point>(val t: T) {
	fun <U> doSomething(t: T, u: U) {
		
	}
}

Korzysta się z typu T klasy, a metoda sama w sobie może mieć własne parametry typu występujące wyłącznie w tej metodzie.

Funkcja sparametryzowana w języku Kotlin

Funkcja sparametryzowana w języku Kotlin zawiera parametr typu ogólnego. Jej nagłówek może wydawać się bardzo nietypowy dla programistów dopiero zapoznających się z typami generycznymi.

Musicie być świadomi tego, że to nadal nie koniec niespodzianek jakie czekają na świeżo upieczonych programistów w języku Kotlin! Niedługo przekonacie się także że to, czy funkcja zwraca parametr typu T, czy przyjmuje taki za parametr formalny, ma OGROMNE znaczenie dla późniejszych modyfikatorów typów generycznych. Jeśli tak Was korci, to możecie już teraz zajrzeć do procesu tworzenia kontrawariancji, a także jak wygląda kowariancja typu sparametryzowanego.


Za przeczytanie dziękuję i życzę najkrótszego czasu na przyswojenie tematu.

PODOBNE ARTYKUŁY