Kotlin to język programowania, przez programistów aplikacji na Androida na całym świecie. Ten temat pełni funkcję Kotlin aby szybko rozpocząć pracę.
Deklaracja zmiennej
Kotlin używa do deklarowania zmiennych dwóch różnych słów kluczowych: val
i var
.
- Użyj
val
w przypadku zmiennej, której wartość nigdy się nie zmienia. Nie można ponownie przypisać wartości do zmiennej zadeklarowanej za pomocą funkcjival
. - Podaj zmienną
var
, której wartość może się zmieniać.
W poniższym przykładzie count
jest zmienną typu Int
, do której przypisano wartość
wartość początkowa 10
:
var count: Int = 10
Int
to typ reprezentujący liczbę całkowitą, jeden z wielu typów liczbowych,
można zapisać w Kotlin. Podobnie jak w przypadku innych języków, możesz także użyć
Byte
, Short
, Long
, Float
i Double
w zależności od Twoich danych liczbowych.
Słowo kluczowe var
oznacza, że w razie potrzeby możesz ponownie przypisać wartości do konta count
. Dla:
na przykład możesz zmienić wartość count
z 10
na 15
:
var count: Int = 10
count = 15
Niektórych wartości nie należy jednak zmieniać. Weźmy pod uwagę: String
o nazwie
languageName
Jeśli chcesz mieć pewność, że languageName
zawsze zawiera wartość
„Kotlin”, możesz zadeklarować languageName
za pomocą słowa kluczowego val
:
val languageName: String = "Kotlin"
Te słowa kluczowe jasno określają, co można zmienić. Wykorzystaj je, aby:
Twoją korzyść. Jeśli odwołanie do zmiennej musi być możliwe do ponownego przypisania,
zadeklaruj go jako var
. W przeciwnym razie użyj val
.
Wnioskowanie typu
Kontynuując poprzedni przykład: gdy przypiszesz wartość początkową do
languageName
, kompilator Kotlin może wywnioskować typ na podstawie typu
przypisanej wartości.
Wartość "Kotlin"
jest typu String
, więc kompilator określa, że
languageName
ma też status String
. Zwróć uwagę, że Kotlin to narzędzie wpisane statycznie.
język. Oznacza to, że typ jest rozpoznawany w czasie kompilacji i nigdy
zmian.
W poniższym przykładzie pole languageName
zostało określone jako String
, więc nie można
wywołaj dowolne funkcje, które nie należą do klasy String
:
val languageName = "Kotlin"
val upperCaseName = languageName.toUpperCase()
// Fails to compile
languageName.inc()
toUpperCase()
to funkcja, która może być wywoływana tylko dla zmiennych danego typu
String
Kompilator Kotlin wywnioskował, że languageName
to String
,
możesz bezpiecznie zadzwonić pod numer toUpperCase()
. inc()
jest natomiast operatorem Int
, więc nie może zostać wywołana przez String
. Podejście Kotlina do pisania
wnioskowanie zapewnia zarówno zwięzłość, jak i bezpieczeństwo typów.
Poziom bezpieczeństwa o wartości null
W przypadku niektórych języków zmienną typu referencyjnego można zadeklarować bez podawania początkowa wartość jawna. W takich przypadkach zmienne zwykle zawierają wartość null. . Zmienne Kotlin nie mogą domyślnie zawierać wartości null. Oznacza to, że ten fragment jest nieprawidłowy:
// Fails to compile
val languageName: String = null
Aby zmienna zawierała wartość null, musi być typu dopuszczalna wartość null. Dostępne opcje
określ zmienną jako dopuszczalną do wartości null, dodając do jej typu sufiks ?
, jak pokazano
w tym przykładzie:
val languageName: String? = null
W przypadku typu String?
możesz przypisać wartość String
lub null
do
languageName
Trzeba ostrożnie obchodzić się ze zmiennymi dopuszczającymi wartości null, ponieważ w przeciwnym razie pojawi się ryzyko
NullPointerException
Jeśli na przykład w Javie spróbujesz wywołać metodę
na wartości null, program ulega awarii.
Kotlin udostępnia wiele mechanizmów do bezpiecznej pracy z wartościami null zmiennych. Więcej informacji: Typowe wzorce Kotlin w Androidzie: dopuszczalność wartości null.
Warunkowe
Kotlin udostępnia kilka mechanizmów do implementacji logiki warunkowej. Najbardziej
jest z nich np. if-else. Jeśli wyrażenie zawiera
w nawiasie obok słowa kluczowego if
zwraca wynik true
, a następnie kod w obrębie
tej gałęzi (czyli kod następujący po nim zapakowany w zakrętkę)
nawiasy klamrowe). W przeciwnym razie wykonywany jest kod w gałęzi else
.
if (count == 42) {
println("I have the answer.")
} else {
println("The answer eludes me.")
}
Za pomocą else if
możesz przedstawić wiele warunków. Dzięki temu możesz reprezentować
bardziej szczegółową, skomplikowaną logikę w ramach pojedynczej instrukcji warunkowej, jak widać w instrukcjach
następujący przykład:
if (count == 42) {
println("I have the answer.")
} else if (count > 35) {
println("The answer is close.")
} else {
println("The answer eludes me.")
}
Wyrażenia warunkowe przydają się do przedstawiania logiki stanowej, ale
że powtarzają się przy ich pisaniu. W przykładzie powyżej
po prostu wydrukuj String
w każdej gałęzi. Aby uniknąć takich powtórzeń, Kotlin oferuje
wyrażenia warunkowe. Ostatni przykład można zapisać tak:
val answerString: String = if (count == 42) {
"I have the answer."
} else if (count > 35) {
"The answer is close."
} else {
"The answer eludes me."
}
println(answerString)
Oznacza to, że każda gałąź warunkowa zwraca wynik wyrażenia na
ostatni wiersz, więc nie musisz używać słowa kluczowego return
. Ponieważ w wyniku
wszystkie 3 gałęzie są typu String
, wynikiem wyrażenia if-else jest
również typu String
. W tym przykładzie do pola answerString
przypisano inicjał
z wyniku wyrażenia if-else. Wykorzystanie wnioskowania typu do:
pomiń deklarację jednoznacznego typu dla answerString
, ale często jest to dobre
uwzględnić go w celu uniknięcia wątpliwości.
Wraz ze wzrostem złożoności stwierdzenia warunkowego możesz rozważyć: zastępując wyrażenie „if-else” wyrażeniem when, jak widać w następujący przykład:
val answerString = when {
count == 42 -> "I have the answer."
count > 35 -> "The answer is close."
else -> "The answer eludes me."
}
println(answerString)
Każda gałąź w wyrażeniu when
jest reprezentowana przez warunek, strzałka
(->
) i wynik. Jeśli warunek po lewej stronie strzałki
zwraca wartość prawda, wynik wyrażenia po prawej stronie wynosi
. Pamiętaj, że wykonanie nie następuje pomiędzy gałęziami.
Kod w przykładowym wyrażeniu when
jest funkcjonalnie odpowiednikiem kodu w
z poprzednim przykładem, ale jest
po prostu łatwiejsza do odczytania.
Fragmenty warunkowe Kotlina podkreślają jedną z bardziej zaawansowanych funkcji, inteligentne przesyłanie. Zamiast używać operatora bezpiecznego połączenia lub parametru not-null do pracy z wartościami dopuszczającymi wartości null, możesz zamiast tego sprawdzić, czy zawiera odniesienie do wartości null za pomocą instrukcji warunkowej, jak w tym przykładzie:
val languageName: String? = null
if (languageName != null) {
// No need to write languageName?.toUpperCase()
println(languageName.toUpperCase())
}
W gałęzi warunkowej pole languageName
może być traktowane jako niedopuszczone do wartości null.
Kotlin jest na tyle inteligentny, że potrafi rozpoznać, że warunek wykonania gałęzi
jest to, że languageName
nie zawiera wartości null, więc nie trzeba traktować
languageName
na wartość null w tej gałęzi. To inteligentne przesyłanie działa w przypadku null
sprawdzanie,
sprawdzanie typu,
lub dowolny warunek, który spełnia
umowa.
Funkcje
W funkcji możesz zgrupować jedno lub więcej wyrażeń. Zamiast powtarzać za każdym razem, gdy potrzebujesz wyniku, możesz zawijać tę samą serię wyrażeń wyrażenia w funkcji i wywołaj tę funkcję.
Aby zadeklarować funkcję, użyj słowa kluczowego fun
, a po nim nazwy funkcji.
Następnie zdefiniuj typy danych wejściowych, które może przyjmować funkcja (o ile takie dane ma) i zadeklaruj
typ zwracanych danych wyjściowych. Treść funkcji to miejsce, w którym określasz
wyrażenia, które są wywoływane podczas wywoływania funkcji.
Nawiązując do poprzednich przykładów, przedstawiamy kompletną funkcję Kotlina:
fun generateAnswerString(): String {
val answerString = if (count == 42) {
"I have the answer."
} else {
"The answer eludes me"
}
return answerString
}
Funkcja w powyższym przykładzie ma nazwę generateAnswerString
. it
nie pobiera żadnych danych. Zwraca wynik typu String
. Aby wywołać
użyj jej nazwy, a po niej operatora wywołania (()
). W
w poniższym przykładzie zmienna answerString
jest inicjowana na podstawie wyniku
generateAnswerString()
val answerString = generateAnswerString()
Funkcje mogą przyjmować argumenty jako dane wejściowe, jak w tym przykładzie:
fun generateAnswerString(countThreshold: Int): String {
val answerString = if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
return answerString
}
Deklarując funkcję, możesz podać dowolną liczbę argumentów i ich
. W powyższym przykładzie generateAnswerString()
przyjmuje 1 argument o nazwie
countThreshold
typu Int
. Możesz w niej odwołać się do funkcji
używając jego nazwy.
Wywołanie tej funkcji wymaga umieszczenia w niej argumentu nawiasy okrągłe:
val answerString = generateAnswerString(42)
Uproszczenie deklaracji funkcji
generateAnswerString()
to dość prosta funkcja. Funkcja deklaruje parametr
i natychmiast zwraca. Gdy wynikiem pojedynczego wyrażenia jest
zwracanych przez funkcję, możesz pominąć deklarowanie zmiennej lokalnej, bezpośrednio
zwracający wynik wyrażenia if-else zawartego w funkcji,
w tym przykładzie:
fun generateAnswerString(countThreshold: Int): String {
return if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
}
Zwracane słowo kluczowe możesz też zastąpić operatorem przypisania:
fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
"I have the answer"
} else {
"The answer eludes me"
}
Funkcje anonimowe
Nie każda funkcja wymaga nazwy. Niektóre funkcje są bardziej bezpośrednio identyfikowane przez oraz ich dane wejściowe i wyjściowe. Są one nazywane funkcjami anonimowymi. Ty może zachować odwołanie do funkcji anonimowej, używając tego odwołania do później można wywołać funkcję anonimową. Możesz też przekazać odnośnik wokół swojego aplikacji, tak jak w przypadku innych typów plików referencyjnych.
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
Podobnie jak funkcje nazwane, funkcje anonimowe mogą zawierać dowolną liczbę wyrażeń. Wartość zwrócona funkcji jest wynikiem wyrażenia końcowego.
W powyższym przykładzie stringLengthFunc
zawiera odniesienie do anonimowego
funkcja, która jako dane wejściowe przyjmuje String
i zwraca długość danych wejściowych
String
jako dane wyjściowe typu Int
. Dlatego typ funkcji to
opisana jako (String) -> Int
. Nie wywołuje on jednak funkcji.
Aby pobrać wynik funkcji, musisz wywołać ją tak samo jak
funkcji nazwanej. Wywołanie stringLengthFunc
wymaga podania wartości String
jako
w tym przykładzie:
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
val stringLength: Int = stringLengthFunc("Android")
Funkcje wyższego rzędu
Funkcja może przyjąć inną funkcję jako argument. Funkcje korzystające z innych funkcji funkcje jako argumenty są nazywane funkcjami wyższego rzędu. Ten wzorzec jest przydatne do komunikacji między komponentami w taki sam sposób, jak interfejsu wywołania zwrotnego w Javie.
Oto przykład funkcji wyższego rzędu:
fun stringMapper(str: String, mapper: (String) -> Int): Int {
// Invoke function
return mapper(str)
}
Funkcja stringMapper()
przyjmuje funkcję String
i funkcję, która
pobiera wartość Int
z przekazanej do niej wartości String
.
Możesz wywołać funkcję stringMapper()
, przekazując element String
i funkcję, która
spełnia drugi parametr wejściowy, czyli funkcję, która przyjmuje funkcję String
jako
wprowadza i zwraca Int
, jak w tym przykładzie:
stringMapper("Android", { input ->
input.length
})
Jeśli funkcja anonimowa jest parametrem last zdefiniowanym w funkcji, możesz poza nawiasami używanymi do wywołania funkcji, jak pokazano w następujący przykład:
stringMapper("Android") { input ->
input.length
}
Funkcje anonimowe można znaleźć w całej bibliotece standardowej Kotlin. Dla: więcej informacji znajdziesz w Funkcje wyższego rzędu i lambda.
Zajęcia
Wszystkie wymienione do tej pory typy są wbudowane w program Kotlin.
język. Jeśli chcesz dodać własny typ niestandardowy, możesz zdefiniować klasę
ze słowem kluczowym class
, jak w tym przykładzie:
class Car
Właściwości
Klasy reprezentują stan za pomocą właściwości. O
property to
zmienną na poziomie klasy, która może zawierać metodę getter, setter i pole Backing.
Ponieważ samochód do jazdy potrzebuje kół, możesz dodać listę obiektów Wheel
jako
właściwości Car
, jak w tym przykładzie:
class Car {
val wheels = listOf<Wheel>()
}
Pamiętaj, że wheels
to public val
, co oznacza, że dostęp do usługi wheels
można uzyskać z poziomu
spoza zajęć Car
i nie można go przypisać. Jeśli chcesz uzyskać
instancji Car
, musisz najpierw wywołać jego konstruktor. Opcje dostępne na tej stronie
uzyskać dostęp do dostępnych właściwości.
val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car
Jeśli chcesz dostosować koła, możesz zdefiniować własny konstruktor, określa sposób inicjowania właściwości klasy:
class Car(val wheels: List<Wheel>)
W powyższym przykładzie konstruktor klas przyjmuje List<Wheel>
jako
jako argumentu konstruktora, który wykorzystuje ten argument do zainicjowania argumentu wheels
usłudze.
Funkcje klasy i hermetyzacja
Klasy używają funkcji do modelowania zachowań. Funkcje mogą zmieniać stan, aby ujawnić tylko te dane, które chcesz ujawnić. Ta kontrola dostępu jest częścią bardziej zorientowaną na obiekt, nazywaną enkapsulacją.
W poniższym przykładzie właściwość doorLock
jest prywatna.
spoza klasy Car
. Aby odblokować samochód, musisz zadzwonić pod numer unlockDoor()
w postaci prawidłowego klucza, jak w tym przykładzie:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
Jeśli chcesz dostosować sposób odwołań do właściwości, możesz podać
metody getter i seter. Na przykład, jeśli chcesz ujawnić
getter, ograniczając dostęp do metody ustawiającej, możesz wyznaczyć ją jako
private
:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
var gallonsOfFuelInTank: Int = 15
private set
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
Dzięki połączeniu właściwości i funkcji możesz tworzyć klasy, które modelowanie wszystkich typów obiektów.
Interoperacyjność
Jedną z najważniejszych cech usługi Kotlin jest płynna interoperacyjność z językiem Java. Kod Kotlin kompiluje się do kodu bajtowego JVM, więc może wywoływać metodę bezpośrednio do kodu Java i odwrotnie. Oznacza to, że możesz korzystać z istniejących bibliotek Java bezpośrednio w kotlinie. Ponadto większość Interfejsy API Androida są napisane w języku Java i można je wywoływać bezpośrednio w Kotlin.
Dalsze kroki
Kotlin to elastyczny, pragmatyczny język, który zyskuje na popularności i wsparciu. Śr zachęcamy do jej wypróbowania, jeśli jeszcze jej nie znasz. Sprawdź, co jeszcze możesz zrobić w oficjalnej dokumentacji Kotlin wraz z instrukcją przesyłania popularnych wzorców Kotlin w Twoich aplikacjach na Androida.