• Dodano: 31.08.2019
  • Sylwester Madej

10 cech, które uwielbiam w języku Kotlin

#

Od chwili, gdy Google ogłosił strategiczne wsparcie dla Kotlina przy tworzeniu aplikacji na Androida minęły ponad dwa lata. W tym czasie Kotlin stał się prawdziwym ulubieńcem developerskiej społeczności. W ubiegłorocznej ankiecie Stack Overflow zajął drugie miejsce pod względem popularności wśród programistów. Ponad trzy czwarte ankietowanych wskazało, że uwielbia w nim programować.

Kotlin ma w sobie coś. Sprawia, że wracając do aplikacji napisanej w Javie, czuję się jakby weekend się skończył. Oto jego 10 cech, które uwielbiam.

10 powodów, dla których warto poznać Kotlina

Kotlin jest językiem nowoczesnym, skrojonym pod współczesne projekty, a do tego dużo przyjemniejszym w użyciu i czytelniejszym od Javy. To przekłada się na większą wydajność projektów, łatwy w utrzymaniu kod oraz niezawodność aplikacji. 

A co konkretnie sprawia, że programowanie w Kotlinie jest łatwe, przyjemne i efektywne? Oto kilka powodów:

1. Opcjonalne średniki.

Javowa składnia wymaga, aby wszystkie polecenia były zakończone średnikami. W Kotlinie możecie o nich zapomnieć. Są one całkowicie opcjonalne.

fun main(args: Array<String>) { //jest fun 
    println("hello, world!") //a brak smutnej minki );
}

2. Nowe obiekty bez new.

W Kotlinie do tworzenia instancji klasy nie potrzebujemy słowa new, zatem nasz kod jest krótszy i bardziej przejrzysty – ułatwia to zarówno jego pisanie, jak i czytanie. W praktyce tworzenie nowych obiektów wygląda tak:

val user = User()

3. Pomijanie typu zmiennej.

Kolejnym przykładem na oszczędność Kotlina jest fakt, że w większości przypadków nie musimy podawać typu zmiennej w kodzie. Kompilator jest go w stanie określić na podstawie wartości zmiennej. Na przykład:

var a = 3.15 //Double
var b = 15f //Float
var c = 30L //Long
var d = 10 //Int
val e = "" //String

4. Opcjonalny void w funkcjach.

Do tego punktu Kotlin podchodzi bardzo pragmatycznie. Otóż jeśli funkcja niczego nam nie zwraca, to nie jest to dla nas interesujące. W związku z tym nie ma potrzeby, aby cokolwiek pisać. Znów odpada nam kilka znaków w kodzie.

fun main() { //zami
}

fun main(): Unit { //to samo, tylko jawnie zadeklarowane
    
}

5. Klasy mogą być znacznie krótsze.

Istotną cechą Kotlina, która ma duży wpływ na czytelność i zwięzłość kodu są krótsze klasy. Po pierwsze, możemy tu pominąć inicjalizatory, gettery i settery wymagane przez Javę. Zamiast tego po prostu oznaczamy zmienną i podajemy jej typ, co wygeneruje nam właściwość (property), która eliminuje potrzebę pisania domyślnych getterów i setterów.

Oto przykład klasy w Kotlinie:

data class Person(var name: String)

I odpowiednik w języku Java:

public final class Person {
   @NotNull private String name;

   @NotNull
   public final String getName() {
      return this.name;
   }
   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name = var1;
   }
   public Person(@NotNull String name) {
      Intrinsics.checkParameterIsNotNull(name, "name");
      super();
      this.name = name;
   }
   @NotNull
   public String toString() {
      return "Person(name=" + this.name + ")";
   }
   public int hashCode() {
      return this.name != null ? this.name.hashCode() : 0;
   }
   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof Person) {
            Person var2 = (Person)var1;
            if (Intrinsics.areEqual(this.name, var2.name)) { return true; }
         }
         return false;
      } else { return true; }
   }
}

Kotlin vs. Java: poza składnią

Wiemy już, jakie cechy Kotlina sprawiają, że kod jest zwięzły, przejrzysty i szybki. A jakie właściwości dają Kotlinowi przewagę nad starą, poczciwą Javą? Oto kolejna piątka:

6. Typowanie statyczne.

W językach typowanych statycznie zmiennym przypisuje się typ na etapie kompilacji. Zaletą tego rozwiązania jest fakt, że kompilator jest w stanie wykryć i poprawić znacznie większą liczbę błędów przed uruchomieniem programu. 

Co prawda Java też jest językiem typowanym statycznie, jednak w mniejszym stopniu niż Kotlin. W rezultacie kod, który w Javie miałby szansę przejść przez kompilator i „wysypałby się” później, w Kotlinie zostanie w porę wychwycony.

Przykładem niech będzie konwersja typu int na double:

int a = 3;
double b = a; //blad
double c = a.toInt(); //jawne rzutowanie

W Javie taka instrukcja zostanie automatycznie wykonana, bez walidacji. Kotlin jest pod tym względem znacznie ostrożniejszy. Wymaga on od nas najpierw ręcznego potwierdzenia, że rzeczywiście chcemy tę konwersję wykonać.

Ta ostrożność powoduje, że wszelkie operacje na typach są weryfikowane z większą dokładnością, a ewentualne nieścisłości w kodzie mogą być szybciej i łatwiej wychwycone.

7. Obsługa nulla.

Znacznik null został wprowadzony do kodowania w latach 60-tych, kiedy jeszcze wydawał się genialnym pomysłem. Z perspektywy czasu, kiedy null pointery napsuły krwi milionom developerów na całym świecie, jego twórca, Tony Hoare, przyznał, że definicja nulla była gigantycznym błędem („Nazywam [nulla] pomyłką na skalę miliardów dolarów”).

W Javie obsługa nulli jest dosyć liberalna. Można je bardzo łatwo przypisywać, ale trudniej potem zidentyfikować. To na developerze ciąży odpowiedzialność, aby odpowiednio zabezpieczyć kod, sprawdzając każdorazowo, czy dane pole nie jest nullem.

Kotlin z nullami radzi sobie znacznie lepiej. Domyślnie nie możemy ich wstawiać, gdzie popadnie. Wartości null można przypisać tylko do pól, które oznaczymy jako nullable, co czynimy poprzez dodanie znaku zapytania na końcu typu, tak jak w tym przykładzie:

var a: Int = null //blad
var b: Int? = null //ok

8. Obsługa argumentów nazwanych i opcjonalnych.

Kolejną cechą Kotlina, która czyni z niego godnego następcę Javy jest obsługa argumentów nazwanych i opcjonalnych. Java w ogóle ich nie wspiera.

Argument nazwany pozwala na przypisanie argumentom w funkcji nazw, co umożliwia wywołanie funkcji z parametrami domyślnymi oraz zwiększa czytelność kodu. Z kolei argumentom opcjonalnym możemy przypisać domyślną wartość, która zostanie nadana, jeśli argument nie będzie wywołany. Na przykład:

fun reformat(str: String,
             normalizeCase: Boolean = true,
             upperCaseFirstLetter: Boolean = true,
             wordSeparator: Char = ' ') {
    //TODO
}

reformat("test", true, false, '_') //wszystkie po kolei
reformat("test") //tylko wymagany parametr
reformat("test", wordSeparator = '_') //ustawianie wartości po nazwie

9. Funkcje Lambda.

Funkcje (lub wyrażenia) Lambda to funkcje anonimowe, nie posiadające nazwy. Stosujemy je w miejscach, w których oczekujemy argumentu będącego interfejsem funkcyjnym, czyli takim, który definiuje tylko i wyłącznie jedną metodę abstrakcyjną (metodę bez implementacji). W Kotlinie możemy użyć takiej funkcji jako parametru innej funkcji.

Oto najprostszy przykład funkcji z wyrażeniem Lambda, bez parametrów:

fun main(args: Array<String>) {
    val greeting = { println("Cześć!")}
    greeting()
}

A oto kolejny przykład, z parametrem:

fun main(args: Array<String>) {
    val product = { a: Int, b: Int -> a * b }
    val result = product(5, 8)
    println(result)
}

W pierwszym przykładzie wyrażeniem Lambda jest { println("Cześć!") },w drugim – { a: Int, b: Int -> a * b }.

Co prawda Java 8 wspiera funkcje Lambda, jednak w Kotlinie są one znacznie bardziej rozbudowane. Poza tym, są one tutaj wbudowane w sam język, nie trzeba zatem stosować takich metod, jak np. biblioteka RetroLambda.

10. Brak wyjątków weryfikowalnych.

Wyjątki weryfikowalne, czyli checked exceptions, są kolejną zmorą programistów, z którą rozprawia się Kotlin. 

W Javie działa to tak: za każdym razem, kiedy chcemy obsłużyć metodę rzucającą wyjątek weryfikowalny, musimy go wyłapać i obsłużyć, albo propagować do innej warstwy. Taki mechanizm przechwytywania i obsługi wyjątków może powodować, że aplikacja będzie niestabilna.

W Kotlinie nie deklarujemy wyjątków, wszystkie one traktowane są de facto jako runtime exceptions. W związku z tym kod pisze się prościej i szybciej. Natomiast w pewnych sytuacjach kompilator nam nie powie, że dana metoda może rzucać błędy, stąd obsługa niektórych wyjątków w Kotlinie może wymagać naszej uwagi. 

Kotlin – więcej niż podstawy

Przytoczyłem tutaj kilka podstawowych faktów o Kotlinie i jego podstawowych właściwościach. Jednak nie tylko one decydują o niesamowitej popularności języka. Kotlin bogaty jest także w inne, bardziej specyficzne funkcjonalności, które znacznie usprawniają pracę developerów i poprawiają jakość kodu. 

Są to cechy takie, jak funkcje rozszerzające (extensions functions), strumienie, funkcja infix, przesłanianie operatorów, konwersje SAM, destrukturyzacja, czy delegacja. Zajmę się nimi w kolejnych postach.

Zacznij przygodę z Kotlinem – obserwuj mój kanał YouTube!

Jak widać powyżej, Kotlin jest niezwykle elastycznym i przydatnym językiem. Jego opanowanie nie sprawia wielkiej trudności, ale wymaga nieco czasu i uporządkowania wiadomości. Jeśli chcesz szybko poznać Kotlina na tyle by móc sprawnie używać go do tworzenia aplikacji na Androida to zapraszam na moje szkolenie: Kotlin dla programistów Androida.

Jeśli wolisz uczyć się w domu i za darmo, to zapraszam na mój kanał na YouTube. Poniżej pierwszy odcinek mojego mini-kursu Kotlina, który nieco szerzej opisuje treści z tego artykułu.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Masz pytania? Sprawdź stronę najczęściej zadawane pytania lub napisz do mnie szkolenia@szkoleniaandroid.pl