Co to jest Kotlin? Wyjaśnienie alternatywy dla języka Java

Kotlin to uniwersalny, darmowy, otwarty, statycznie typowany, „pragmatyczny” język programowania, początkowo zaprojektowany dla JVM (Java Virtual Machine) i Androida, który łączy w sobie funkcje programowania obiektowego i funkcjonalnego. Koncentruje się na interoperacyjności, bezpieczeństwie, przejrzystości i wsparciu narzędziowym. Wersje Kotlin ukierunkowane na JavaScript ES5.1 i kod natywny (przy użyciu LLVM) dla wielu procesorów są również w produkcji.

Kotlin powstał w JetBrains, firmie stojącej za IntelliJ IDEA, w 2010 r. I jest open source od 2012 r. Zespół Kotlin ma obecnie ponad 90 pełnoetatowych członków z JetBrains, a projekt Kotlin na GitHub ma ponad 300 współpracowników. JetBrains wykorzystuje Kotlin w wielu swoich produktach, w tym we flagowym IntelliJ IDEA.

Kotlin jako bardziej zwięzły język Java

Na pierwszy rzut oka Kotlin wygląda na bardziej zwięzłą i usprawnioną wersję Javy. Rozważ powyższy zrzut ekranu, na którym automatycznie przekonwertowałem przykładowy kod Java (po lewej) na Kotlin. Zwróć uwagę, że bezmyślne powtarzanie związane z tworzeniem instancji zmiennych Java zniknęło. Idiom Java

StringBuilder sb = new StringBuilder ();

Staje się w Kotlinie

val sb = StringBuilder ()

Możesz zobaczyć, że funkcje są zdefiniowane za pomocą funsłowa kluczowego i że średniki są teraz opcjonalne, gdy obecne są znaki nowej linii. valKluczowe deklaruje właściwość tylko do odczytu lub zmiennej lokalnej. Podobnie, varsłowo kluczowe deklaruje zmienną właściwość lub zmienną lokalną.

Niemniej jednak Kotlin jest mocno typowany. valI varsłowa kluczowe mogą być stosowane tylko wtedy, gdy typ można wywnioskować. W przeciwnym razie musisz zadeklarować typ. Wnioskowanie o typach wydaje się poprawiać z każdym wydaniem Kotlina.

Spójrz na deklarację funkcji w górnej części obu okienek. Zwracany typ w Javie poprzedza prototyp, ale w Kotlinie zastępuje prototyp, oznaczony dwukropkiem, jak w Pascalu.

Nie jest to całkowicie oczywiste z tego przykładu, ale Kotlin złagodził wymóg Javy, aby funkcje były członkami klas. W Kotlinie funkcje mogą być deklarowane na najwyższym poziomie w pliku, lokalnie wewnątrz innych funkcji, jako funkcja składowa wewnątrz klasy lub obiektu oraz jako funkcja rozszerzająca. Funkcje rozszerzające zapewniają podobną do języka C # możliwość rozszerzania klasy o nowe funkcje bez konieczności dziedziczenia z klasy lub używania dowolnego typu wzorca projektowego, takiego jak dekorator.

Dla fanów Groovy Kotlin wdraża konstruktorów; w rzeczywistości konstruktorzy Kotlin mogą być sprawdzani pod względem typu. Kotlin obsługuje właściwości delegowane, których można używać do implementowania właściwości leniwych, właściwości obserwowalnych, właściwości podlegających zawetowaniu i właściwości mapowanych.

Wiele mechanizmów asynchronicznych dostępnych w innych językach można zaimplementować jako biblioteki za pomocą coroutines Kotlin. Obejmuje to async/ awaitz C # i ECMAScript, kanały i wybierz z Go i generators/ yieldz C # i Python.

Programowanie funkcjonalne w Kotlinie

Dopuszczenie funkcji najwyższego poziomu to dopiero początek historii programowania funkcjonalnego dla Kotlina. Język obsługuje również funkcje wyższego rzędu, funkcje anonimowe, wyrażenia lambda, funkcje wbudowane, zamknięcia, rekurencję ogonową i typy ogólne. Innymi słowy, Kotlin posiada wszystkie cechy i zalety języka funkcjonalnego. Rozważmy na przykład następujące funkcjonalne idiomy Kotlina.

Filtrowanie listy w Kotlin

val positives = list.filter {x -> x> 0}

Aby uzyskać jeszcze krótsze wyrażenie, użyj, itgdy w funkcji lambda jest tylko jeden parametr:

val positives = list.filter {it> 0}

Przemierzanie mapy / listy par w Kotlinie

for ((k, v) in map) {println („$ k -> $ v”)}

kv można go nazwać wszystkim.

Używanie zakresów w Kotlin

for (i in  1..100) {...} // zakres zamknięty: obejmuje 100

for (i in  1 do 100) {...} // półotwarty zakres: nie obejmuje 100

for (x in  2..10 step 2) {...}

for (x in  10 downTo 1) {...}

if (x in  1..10) {...}

Powyższe przykłady pokazują  for słowo kluczowe, a także użycie zakresów.

Mimo że Kotlin jest pełnoprawnym funkcjonalnym językiem programowania, zachowuje większość obiektowego charakteru Javy jako alternatywnego stylu programowania, co jest bardzo przydatne podczas konwertowania istniejącego kodu Java. Kotlin ma klasy z konstruktorami, a także zagnieżdżone, wewnętrzne i anonimowe klasy wewnętrzne i ma interfejsy takie jak Java 8. Kotlin nie ma newsłowa kluczowego. Aby utworzyć instancję klasy, wywołaj konstruktor tak jak zwykłą funkcję. Widzieliśmy to na powyższym zrzucie ekranu.

Kotlin ma pojedyncze dziedzictwo z nazwanej nadklasy, a wszystkie klasy Kotlin mają domyślną superklasę Any, która nie jest tym samym, co klasa podstawowa Java java.lang.Object. Anyzawiera tylko trzy predefiniowane funkcje składowe: equals(), hashCode(), i toString().

Klasy Kotlin muszą być oznaczone opensłowem kluczowym, aby inne klasy mogły po nich dziedziczyć; Klasy Java są odwrotne, ponieważ są dziedziczone, chyba że są oznaczone finalsłowem kluczowym. Aby przesłonić metodę nadklasy, należy oznaczyć samą metodę open, a metodę podklasy override. To wszystko jest częścią filozofii Kotlina, polegającej na wyjaśnianiu rzeczy, a nie poleganiu na domyślnych. W tym konkretnym przypadku widzę, gdzie sposób Kotlina na jawne oznaczanie członków klasy bazowej jako otwartych do dziedziczenia, a członków klas pochodnych jako przesłonięcia pozwala uniknąć kilku rodzajów typowych błędów Java.

Zabezpieczenia w Kotlin

Mówiąc o unikaniu typowych błędów, Kotlin został zaprojektowany w celu wyeliminowania niebezpieczeństwa odwołań do zerowych wskaźników i usprawnienia obsługi wartości null. Robi to, czyniąc nullniedozwolone dla typów standardowych, dodając typy dopuszczające wartość null i implementując notacje skrótów do obsługi testów dla null.

Na przykład zwykła zmienna typu  nie może zawierać  :String null

var a: String = "abc"

a = null // błąd kompilacji

Jeśli chcesz zezwolić na wartości null, na przykład w celu przechowywania wyników zapytania SQL, możesz zadeklarować typ dopuszczający wartość null, dodając znak zapytania do typu, np String?.

var  b: String?

b = null  // ok

Zabezpieczenia idą trochę dalej. Można bezkarnie użyć typu dopuszczającego wartość null, ale przed jego użyciem należy przetestować typ dopuszczający wartość null dla wartości null.

Aby uniknąć szczegółowej gramatyki normalnie potrzebnej do testowania zerowego, Kotlin wprowadza bezpieczne wywołanie , napisane ?.. Na przykład zwraca, jeśli nie jest , aw przeciwnym razie. Typ tego wyrażenia to .b?.length b.lengthbnullnullInt?

Innymi słowy, b?.lengthjest skrótem do if (b != null) b.length else null. Ta składnia ładnie łączy się w łańcuchy, eliminując sporo logiki prolix, zwłaszcza gdy obiekt został zapełniony z serii zapytań do bazy danych, z których każde mogło się nie powieść. Na przykład, bob?.department?.head?.namezwróci imię i nazwisko szefa działu Roberta, jeśli Bob, dział i szef działu nie są zerowe.

Aby wykonać określoną operację tylko dla wartości innych niż null, możesz użyć bezpiecznego operatora połączenia ?.razem z  let:

val listWithNulls: List = listOf ("A", null)

for (item in listWithNulls) {

      item? .let {println (it)} // wyświetla A i ignoruje wartość null}

Często chcesz zwrócić prawidłową, ale specjalną wartość z wyrażenia dopuszczającego wartość null, zazwyczaj w celu zapisania go w typie niedopuszczającym wartości null. Jest do tego specjalna składnia zwana operatorem Elvisa (nie żartuję), napisana ?:.

val l = b? .length?: -1

jest odpowiednikiem 

val l: Int = if (b! = null) b.length else -1

W tym samym duchu Kotlin pomija sprawdzone wyjątki Javy, które są warunkami do rzucania, które należy złapać. Na przykład podpis JDK

Appendable append (CharSequence csq) zgłasza  IOException;

wymaga, abyś złapał za IOExceptionkażdym razem, gdy wywołujesz appendmetodę:

próbować {

  log.append (wiadomość)

}

catch (IOException e) {

  // Zrób coś z wyjątkiem

}

Projektanci Javy uważali, że to dobry pomysł i był to wynik netto dla programów-zabawek, o ile programiści zaimplementowali w catchklauzuli coś sensownego . Zbyt często w dużych programów Java, jednak widać kod, w którym obowiązkowo catchklauzula zawiera nic poza komentarz: //todo: handle this. To nikomu nie pomaga, a sprawdzone wyjątki okazały się stratą netto dla dużych programów.

Kotlin coroutines

Coroutines w Kotlin to w zasadzie nici lekkie. Zaczynasz je za pomocą launchnarzędzia do tworzenia programów w kontekście niektórych CoroutineScope. Jednym z najbardziej użytecznych zakresów programu jest ten runBlocking{}, który dotyczy zakresu jego bloku kodu.

import kotlinx.coroutines. *

fun main () = runBlocking {// this: CoroutineScope

    launch {// uruchom nowy coroutine w zakresie runBlocking

        delay (1000L) // nieblokujące opóźnienie przez 1 sekundę

        println ("Świat!")

    }

    println ("Cześć")

}

Ten kod generuje następujące dane wyjściowe z jednosekundowym opóźnieniem między wierszami:

Dzień dobry,

Świat!

Kotlin na Androida

Do maja 2017 roku jedynymi oficjalnie obsługiwanymi językami programowania dla Androida były Java i C ++. Firma Google ogłosiła oficjalne wsparcie dla Kotlin na Androida na Google I / O 2017, a począwszy od Android Studio 3.0 Kotlin jest wbudowany w zestaw narzędzi programistycznych Androida. Kotlin można dodać do wcześniejszych wersji Android Studio za pomocą wtyczki.

Kotlin kompiluje się do tego samego kodu bajtowego co Java, współdziała z klasami Java w naturalny sposób i współdzieli swoje narzędzia z Javą. Ponieważ nie ma narzutów związanych z nawiązywaniem połączeń między Kotlinem a Javą, dodawanie Kotlina przyrostowo do aplikacji na Androida obecnie w Javie ma sens. Nieliczne przypadki, w których interoperacyjność między kodem Kotlin i Java nie jest wdzięczna, na przykład właściwości tylko zestawu Java, są rzadko spotykane i łatwe do naprawienia.

Pinterest był dzieckiem plakatu dla aplikacji na Androida napisanych w Kotlinie już w listopadzie 2016 r. I wspomniano o tym wyraźnie na Google I / O 2017 w ramach ogłoszenia Kotlin. Ponadto zespół Kotlin lubi cytować aplikacje Evernote, Trello, Square i Coursera na Androida.

Kotlin kontra Java

Pytanie, czy wybrać Kotlin lub Javę do nowego rozwoju, pojawiło się w społeczności Androida od czasu ogłoszenia Google I / O, chociaż ludzie zadawali to pytanie już w lutym 2016 r., Kiedy pojawił się Kotlin 1.0. Krótka odpowiedź jest taka, że ​​kod Kotlin jest bezpieczniejszy i bardziej zwięzły niż kod Java, a pliki Kotlin i Java mogą współistnieć w aplikacjach na Androida, dzięki czemu Kotlin jest przydatny nie tylko w nowych aplikacjach, ale także w rozszerzaniu istniejących aplikacji Java.

Jedynym przekonującym argumentem przemawiającym za wyborem Javy zamiast Kotlina byłby przypadek początkujących programistów Androida. Dla nich może istnieć bariera do pokonania, biorąc pod uwagę, że historycznie większość dokumentacji i przykładów Androida jest w Javie. Z drugiej strony konwersja Javy na Kotlin w Android Studio jest prostą sprawą wklejenia kodu Java do pliku Kotlin.

Dla prawie każdego, kto zajmuje się programowaniem na Androida, zalety Kotlin są przekonujące. Typowy czas przeznaczony dla programisty Java na naukę Kotlina to kilka godzin - niewielka cena za wyeliminowanie zerowych błędów referencyjnych, włączenie funkcji rozszerzeń, wsparcie programowania funkcjonalnego i dodanie programów. Typowe przybliżone szacunki wskazują na około 40-procentowe zmniejszenie liczby linii kodu z języka Java do Kotlin.