primerjava programskih jezikov java in kotlin na … · dodali so ga, ker so želeli imeti boljši...
TRANSCRIPT
UNIVERZA V MARIBORU
FAKULTETA ZA ELEKTROTEHNIKO,
RAČUNALNIŠTVO IN INFORMATIKO
Nikolaj Čolić
PRIMERJAVA PROGRAMSKIH JEZIKOV JAVA IN KOTLIN NA PRIMERU IMPLEMENTACIJE APLIKACIJE
JAZGOBAR
Diplomsko delo
Maribor, junij 2018
PRIMERJAVA PROGRAMSKIH JEZIKOV JAVA IN KOTLIN NA
PRIMERU IMPLEMENTACIJE APLIKACIJE JAZGOBAR
Diplomsko delo
Študent: Nikolaj Čolić
Študijski program: Visokošolski strokovni
Smer: Računalništvo in informacijske tehnologije
Mentor: doc. dr. Matej Črepinšek
Lektorica: Valentina Toman Čremožnik
I
ZAHVALA Prijazno se zahvaljujem mentorju, doc. dr. Mateju Črepinšku, za izkazano zaupanje ter vso
pomoč pri nastajanju diplomskega dela. Prav tako se zahvaljujem družini, ki mi je med
študijem stala ob strani ter me celostno podpirala.
II
Primerjava programskih jezikov Java in Kotlin na primeru implementacije aplikacije JazGobar
Ključne besede: Java, Kotlin, Android
UDK: 004.43:621.397.7-026.26(043.2)
Povzetek
V zaključnem delu bomo primerjali programska jezika Java in Kotlin na primeru mobilne
aplikacije JazGobar. Najprej se bomo seznanili z obema programskima jezikoma, ki ju
bomo primerjali na podlagi podanih primerov, ter preučili njune prednosti. Aplikacijo
bomo razvili za Android operacijski sistem v obeh zgoraj omenjenih programskih jezikih s
pomočjo Android Studia.
III
The Comparison of Programming Languages Java and Kotlin in the Case of JazGobar application Implementation
Key words: Java, Kotlin, Android
UDK: 004.43:621.397.7-026.26(043.2)
Abstract
In our final thesis, we will compare the programming languages Java and Kotlin using the
example of the mobile application JazGobar. First, we will get acquainted with both
programming languages which we will compare based on the given examples, and study
their advantages. By using Android Studio, we will develop the application for the Android
operating system in both programming languages mentioned above.
IV
KAZALO
1 UVOD ....................................................................................................... 1
2 PREDSTAVITEV UPORABLJENEGA ORODJA IN TEHNOLOGIJE ................. 3
2.1 Android Studio ............................................................................................................................... 3
2.2 Android operacijski sistem ............................................................................................................. 4
3 PROGRAMSKI JEZIKI ................................................................................ 5
3.1 Zgodovina programskih jezikov ...................................................................................................... 6
3.2 Programski jezik Java ..................................................................................................................... 8
3.3 Programski jezik Kotlin ................................................................................................................... 8
4 PRIMERJAVA JAVE IN KOTLINA ............................................................. 10
4.1 Osnovni tipi .................................................................................................................................. 10
4.2 Spremenljivke .............................................................................................................................. 11
4.3 Inicializacija razreda ..................................................................................................................... 12
4.4 Funkcije ........................................................................................................................................ 13
4.5 Lastnosti ....................................................................................................................................... 14
4.6 Zanke ........................................................................................................................................... 15
4.7 Delo s seznami ............................................................................................................................. 17
4.8 Povezovanje komponent .............................................................................................................. 18
4.9 Vmesniki ...................................................................................................................................... 19
5 PREDNOSTI PROGRAMSKEGA JEZIKA KOTLIN ....................................... 21
5.1 Izrazitost ...................................................................................................................................... 21
V
5.2 Null varnost .................................................................................................................................. 23
5.3 Enostavno učenje ......................................................................................................................... 25
5.4 Razširitvene funkcije .................................................................................................................... 25
5.5 Interoperabilnost ......................................................................................................................... 26
5.6 Pametno pretvarjanje .................................................................................................................. 26
5.7 Funkcije višjega reda in lambda izrazi ........................................................................................... 27
6 PREDNOSTI PROGRAMSKEGA JEZIKA JAVA ........................................... 28
7 MOBILNA APLIKACIJA JAZGOBAR .......................................................... 31
7.1 Opis ideje ..................................................................................................................................... 31
7.2 Implementacija ............................................................................................................................ 32
7.3 Uporabniški vmesnik .................................................................................................................... 32
7.4 Povezava elementov s programsko kodo ..................................................................................... 34
7.5 Meni ............................................................................................................................................. 35
7.6 Eventbus ...................................................................................................................................... 36
7.7 Shranjevanje podatkov o uporabniku ........................................................................................... 37
7.8 Dodajanje lokacij gob ................................................................................................................... 39
7.9 Shranjevanje in pridobivanje podatkov ........................................................................................ 41
7.10 Prikaz lokacij gob .......................................................................................................................... 45
7.11 Prikaz podrobosti o lokaciji gobe v novem oknu ........................................................................... 46
7.12 Končni izdelek .............................................................................................................................. 47
8 SKLEP ..................................................................................................... 48
LITERATURA IN VIRI ..................................................................................... 50
VI
KAZALO SLIK
SLIKA 2.1: ANDROID STUDIO IKONA...................................................................................................................... 3
SLIKA 2.2: ANDROID LOGOTIP ............................................................................................................................. 4
SLIKA 3.1: ALGOLSKI JEZIKI ................................................................................................................................ 7
SLIKA 3.2: DUKE, MASKOTA JAVE ......................................................................................................................... 8
SLIKA 3.3: KOTLIN IKONA ................................................................................................................................... 8
SLIKA 6.1: PRIMERJAVA ČASA PREVAJANJA Z GRADLOM V OBEH PROGRAMSKIH JEZIKIH .................................................... 28
SLIKA 6.2: PRETVROBA JAVANSKE KODE V KOTLIN .................................................................................................. 29
SLIKA 7.1: IKONA APLIKACIJE JAZGOBAR .............................................................................................................. 31
SLIKA 7.2: IZGRADNJA UPORABNIŠKEGA VMESNIKA ................................................................................................. 33
SLIKA 7.3: DELOVANJE EVENTBUS-A ................................................................................................................... 36
SLIKA 7.4: PODATKOVNI MODEL ........................................................................................................................ 43
SLIKA 7.5: IZGLED VRSTICE SEZNAMA .................................................................................................................. 45
SLIKA 7.6: SEZNAM LOKACIJ GOB V MOBILNI APLIKACIJI JAZGOBAR ............................................................................. 46
SLIKA 7.7: PRIKAZ PODROBNOSTI O LOKACIJI GOB V MOBILNI APLIKACIJI JAZGOBAR......................................................... 46
SLIKA 8.1: PRIMERJAVA PROGRAMSKIH JEZIKOV JAVA IN KOTLIN ................................................................................ 49
KAZALO TABEL
TABELA 1: PRIMERJAVA VELIKOSTI IN PORABE POMNILNIKA MED OBEMA APLIKACIJAMA ................................................... 47
VII
SEZNAM KRATIC
API - Application programming interface
APK - Application Package Kit
GPS - Global Positioning System
IDE - Integrated development environment
JSON - JavaScript Object Notation
JVM - Java virtual machine
MB - Megabyte
OS - Operacijski sistem
PHP - PHP: Hypertext Preprocessor
RAM - Random-access memory
XML - Extensible Markup Language
1
1 UVOD
Android operacijski sistem je poleg iOS-a eden izmed vodilnih mobilni operacijskih
sistemov na trgu. Od leta 2008 najdemo Android operacijski sistem na mobilnih napravah
in tabličnih računalnikih različnih proizvajalcev. Android ima v svoji trgovini (Google Play)
več milijonov aplikacij, ki so večinoma razvite s pomočjo Android Studia in posledično s
programskim jezikom Java. Google je želel, da bi razvijalci lahko z manj napisane
programske kode naredili enako stvar, zato je oktobra 2017 v Android Studio dodal
programski jezik Kotlin. Kotlin je poleg Jave postal uradni programski jezik Android Studia.
Dodali so ga, ker so želeli imeti boljši programski jezik kot Java, ki pa ohranja
kompatibilnost z njo.
Seznanili se bomo s Kotlin programskim jezikom, ga preučili in primerjali z Javo. V
teoretičnem delu zaključnega dela bomo analizirali enostavnost in prednosti
programskega jezika Kotlin. Prav tako bomo analizirali zahtevnost preskoka iz
programskega jezika Java v programski jezik Kotlin. Za praktični del naloge bomo izdelali
mobilno aplikacijo JazGobar za operacijski sistem Android. Sprva bomo aplikacijo izdelali v
Javi, nato jo bomo s pomočjo Android Studia pretvorili v Kotlin programski jezik.
Predstavili bomo uporabljeno orodje in tehnologijo pri razvoju zaključnega dela. Opisali
bomo zgodovino razvoja programskih jezikov in predstavili programska jezika Javo in
Kotlin. Sledi natančna primerjava med programskima jezikoma. Primerjali bomo
naslednje:
• inicializacijo razreda,
• uporabo zank,
• spremenljivke,
• funkcije,
• lastnoti,
• vmesnike.
2
Poleg tega bomo navedli in natančno opisali še vse prednosti, ki jih ponuja programski
jezik Kotlin, in prednosti programskega jezika Java. Na koncu bomo predstavili
implementacijo aplikacije JazGobar ter pokazali zaminive odseke kode v obeh
programskih jezikih.
3
2 PREDSTAVITEV UPORABLJENEGA ORODJA IN TEHNOLOGIJE
V tem poglavju bomo predstavili orodje in tehnologijo, ki smo ju uporabili pri izdelavi
zaključnega dela.
2.1 Android Studio
Android Studio (Slika 2.1) je uradno razvijalsko okolje za Googlov Android operacijski
sistem, ki ga lahko prenesemo na Windows, macOS in Linux operacijski sistem. Konec leta
2014 je izšla uradna verzija programa. To so predstavili kot zamenjavo za orodje Eclipse.
Razvijalci lahko razvijajo z Javo, C++ in XML-jem. XML se uporablja za vizualni del
aplikacije, Java in C++ nam pa omogočata delovanje aplikacije. Programski jezik
razvijalcem ni delal težav, saj so ga poznali že prej, morali so se navaditi samo na nov
uporabniški vmesnik programa [1].
Slika 2.1: Android Studio ikona (Vir: Wikipedia, https://en.wikipedia.org/wiki/Android_Studio)
Poleg programa za razvijanje dobimo tudi Android Virtual Device, ki nam omogoča
poganjanje emulatorja in posledično tudi Android aplikacije. To je uporabno predvsem
takrat, ko nimamo telefona z Android operacijskim sistemom oz. primernega telefona za
4
testiranje aplikacije, ki jo razvijamo. Na emulatorju lahko izvajamo vse operacije, kot da bi
imeli pravi telefon [2].
2.2 Android operacijski sistem
Android (Slika 2.2) je mobilni operacijsi sistem, ki ga je razvilo podjetje Google. Zasnovan
je predvsem za mobilne naprave z zaslonom na dotik, kot so pametni telefoni in tablični
računalniki. Google je dodatno razvil Android TV za televizorje, Android Auto za
avtomobile in Wear OS za pametne ure. Različice Androida se uporabljajo tudi na igralnih
konzolah, digitalnih fotoaparatih, osebnih računalnikih in drugi elektroniki [3].
Slika 2.2: Android logotip (Vir: Wikipedia, https://en.wikipedia.org/wiki/Android_(operating_system))
Prvotno je Android razvilo podjetje Android Inc., ki ga je leta 2005 kupil Google. Google je
Android operacijski sistem predstavil leta 2007, leto za tem pa je predstavil prvo
komercialno Android napravo. Operacijski sistem je od takrat dobil kar nekaj različic.
Trenutna različica je 8.1, imenovana je »Oreo«, ki je bila objavljena decembra 2017 [3].
Android je od leta 2011 po celem svetu najbolj prodajan operacijski sistem za pametne
telefone. Od maja 2017 ima več kot dve milijardi mesečno aktivnih uporabnikov in več kot
3,5 milijonov aplikacij v svoji trgovini (Google Play) [3].
5
3 PROGRAMSKI JEZIKI
»Trenutno obstaja več kot 3.000 programskih jezikov in v prihodnosti lahko pričakujemo
še večji razmah. Zato je nemogoče pričakovati, da bomo vedno uporabljali samo en
programski jezik. Vsekakor pa nikoli ne bo obstajal en sam univerzalni jezik! Zato mora
programer dobro poznati osnovne principe (koncepte) programskih jezikov. Tako se bo
veliko hitreje naučil novega, njemu še neznanega programskega jezika. Če dobro
poznamo principe programskih jezikov, jih tudi lažje ocenjujemo. Izbira programskega
jezika je ena izmed pomembnih odločitev« [4].
»Nekateri programski jeziki so primerni za hitre rešitve in prototipiranje, spet drugi za
večje projekte. Tako je sposobnost ocenjevanja jezika zelo pomembna pri določanju
uporabnosti programskega jezika. Poznavanje principov programskih jezikov je tudi pogoj
za uspešno načrtovanje novih. Mnogi ne bodo nikoli načrtovali splošnonamenskega
programskega jezika, prav gotovo pa se bodo srečali z načrtovanjem in implementacijo
kakšnega domensko specifičnega jezika, npr. vprašalnega jezika (»query language«). V
tem primeru bo pridobljeno znanje zelo koristno. S študijem programskih jezikov
spoznamo tudi njihovo implementacijo, kar nam pomaga pri razumevanju programskega
jezika in tudi pri samem programiranju« [4].
»Posamezni programski jeziki imajo različne značilnosti in poglede na načrtovanje in opis
algoritmov, podatkovnih in krmilnih struktur. Z učenjem novih programskih jezikov
najdemo nove poti za izražanje svojih idej. Programski jeziki so temelj računalništva in
brez njihovega podrobnega poznavanja ne moremo biti uspešni« [4].
»Da je programski jezik uporaben, mora zadoščati določenim zahtevam. Programski jezik
naj bo univerzalen, tako da omogoča zapis vsake rešljive naloge v izbrani domeni. Na prvi
pogled je to zelo stroga zahteva, vendar je univerzalen že vsak jezik, v katerem lahko
definiramo rekurzivne funkcije. Nadalje zahtevamo, naj programski jezik omogoča
reševanje naloge na naraven način vsaj s področja njegove uporabe, kot so npr:
6
znanstvene aplikacije, poslovne aplikacije, umetna inteligenca, sistemsko programiranje
itd. S programskim jezikom, katerega edini podatkovni tip so števila in polja, lahko na
naraven način rešujemo naloge iz numeričnega procesiranja. Manj primeren je za
reševanje nalog umetne inteligence. Programski jezik je uporaben, če ga je mogoče
implementirati na računalniku na učinkovit način« [4].
3.1 Zgodovina programskih jezikov
»Čeprav je od prvega digitalnega računalništva preteklo samo dobrih 50 let, je bilo v tem
obdobju na področju programskih jezikov kar nekaj pomembnih mejnikov. Programski
jeziki imajo tudi svojo predzgodovinsko obdobje, in sicer, ko računalniki še sploh niso
obstajali. Obstajali pa so formalni modeli računanja in ideje, kako bi zapisovali programe«
[4].
»Začetna, 50. in 60. leta prejšnjega stoletja, lahko označimo kot izumiteljska, saj je bilo
mnogo novosti: zbirniki, prevajalniki, interpreterji, prvi visoki programski jeziki, strukturno
programiranje, abstrakcija, formalna sintaksa, objektno usmerjeno programiranje,
funkcijsko programiranje, vertifikacija programov itd. V letih, ki so sledila (70., 80., 90.),
takšnega napredka in novih revolucionarnih idej ni bilo več. Osnovne ideje so bile
izboljšane, sledila je učinkovitejša implementacija, teorija je postala bolj praktična itd.«
[4].
»Današnje programske jezike načrtujemo iz izkušenj, ki smo jih dobili pri načrtovanju
predhodnih programskih jezikov. Programski jeziki se neprestano razvijajo in izboljšujejo,
zato je skoraj nemogoče napovedati, kakšno bo stanje na tem področju čez nekaj let. Prva
visoka programska jezika sta bila fortan in cobol. Osnovni cilj, ki so ga imeli načrtovalci
fortana, je bilo učinkovito izvajanje generirane objektne kode. Tako je prevajalnik za
fortan tudi prvi prevajalnik s fazo optimizacije. Sam programski jezik je imel veliko
pomanjkljivosti in neregularnosti. Samemu načrtovanju jezika niso posvečali veliko
pozornosti, saj so menili, da je to enostavno opravilo. Fortan je vpeljal simbolične izraze in
podprograme s parametri« [4].
7
Slika 3.1: Algolski jeziki (Vir: M. Mernik, V. Žumer, Programski jeziki, Inštitut za računalništvo)
»Programski jezik algol-60 je zelo vplival na razvoj mnogih programskih jezikov, ki jih zato
imenujemo tudi algolski jeziki (Slika 3.1). Programska jezika fortran in algol-60 sta bila
namenjena predvsem numeričnemu računanju, medtem ko je bil jezik cobol bolj
primeren za obdelovanje poslovnih podatkov. Programski jezik PL/I je bil načrtovan z
namenom, da postane splošnonamenski jezik. Tako so v njem združene značilnosti
prejšnih treh jezikov. Vpeljal je tudi nove koncepte, kot so izjeme in sočasnost. Tako je
PL/I postal obsežen jezik, ki se ga je bilo težko naučiti, uporabljati in implementirati.
Izkušnje z jezikom PL/I so pokazale, da je za razvoj splošnonamenskega jezika neprimerno
združevati samo značilnosti drugih jezikov. Boljši način je bil, da so izbrali primerno
množico konceptov in jih sistematično združili« [4].
»Takšen pristop so ubrali načrtovalci programskega jezika algol-60, kjer lahko npr.
definiramo polje števil, polje polj, polje procedur, in procedure lahko vračajo tako števila
kot polja ter procedure. Značilnosti programskega jezika algol-60 so: uporabniško
definirani tipi, strukturna ekvivalenca tipov, disjunktna unija, referenčni tip, fleksibilna
polja. Čeprav so načrtovalci programskega jezika algol-60 težili k majhni množici
neodvisnih konceptov, so le-ti povezani med seboj na zelo kompleksen način. Berljivost in
razumljivost tako zapisanih programov je slabša« [4].
8
3.2 Programski jezik Java
Java (Slika 3.2) je splošnonamenski programski jezik, ki je konkurenčen, objektno
orientiran in zasnovan tako, da je čim manj implementacijsko odvisen. Narejen je tako, da
omogoča razvijalcem, da razvijejo kodo enkrat in jo poganjajo kjerkoli. To pomeni, da se
lahko prevedena javanska koda izvaja na vseh platformah, ki podpirajo Javo. Od leta 2016
je Java najbolj uporabljen programski jezik predvsem za aplikacije tipa odjemalec-strežnik.
Java ima veliko sintaks iz programskih jezikov C in C++. Zadnja različica je Java 10, ki je bila
izdana marca 2018, samo pol leta za tem, ko je izšla Java 9 [5].
Slika 3.2: Duke, maskota Jave (Vir:
https://sl.wikipedia.org/wiki/Programski_jezik_java#/media/File:Duke.wave.shadow.png)
3.3 Programski jezik Kotlin
Kotlin (Slika 3.3) je statični programski jezik, ki se je pojavil leta 2011. Izvaja se na JVM.
Lahko ga prevedemo tudi v JavaScript izvorno kodo. Sintaksa Kotlina ni združljiva s
programskim jezikom Java, temveč omogoča povezljivost z njo. To pomeni, da lahko
imamo v enem projektu tako javansko kodo kot Kotlin (seveda v ločenih datotekah), pa
bo program popolnoma delujoč [6].
Slika 3.3: Kotlin ikona (Vir: https://en.wikipedia.org/wiki/Kotlin_(programming_language)#/media/File:Kotlin-
logo.png)
9
Od Android Studia 3.0, ki je izšel oktobra 2017, je Kotlin postal v celoti podprt programski
jezik za razvoj mobilnih aplikacij Android. Vključen je v Android Studio kot alternativa
programskemu jeziku Java. Zadnja različica Kotlina je 1.2.30, ki je izšla marca 2018 [6].
10
4 PRIMERJAVA JAVE IN KOTLINA
Za Java razvijalce je Kotlin zelo intiutiven in enostaven programski jezik za učenje. Večji
del programskega jezika Kotlin je zelo podoben temu, kar že poznamo, razlike so le v
principu (konceptu), ki ga hitro usvojimo. Android Studio razume, prevaja in poganja
kodo, napisano v Kotlinu. Podjetje, ki razvija IDE, zagotavlja podporo programskemu
jeziku Kotlin, kar pomeni, da smo Android razvijalci v dobrem položaju [7].
Naslednji primeri so povzeti in prilagojeni iz knjige Kotlin for Android Developers [7] ter
spletnih strani Yalantis [8], Kotlinlang [9] in Tutorialspoint [10] .
4.1 Osnovni tipi
V programskem jeziku Kotlin ne najdemo takšnih primitivnih tipov, kot jih uporabljamo v
programskem jeziku Java. To je zelo dobro, saj imamo homogen način za delo z
obstoječimi tipi. Seveda še zmeraj najdemo osnovne tipe, kot so »integer«, »float«,
»char« in »boolean«, ampak se vsi obnašajo kot objekt. Imena osnovnih tipov in njihovo
obnašanje je zelo podobno kot v programskem jeziku Java, ampak še zmeraj obstaja nekaj
razlik [7]:
• Ne obstaja direktna pretvorba med numeričnimi tipi (npr. ne moremo Int
vrednosti dodeliti spremenljivki tipa Double). Lahko pa to storimo z eksplicitno
pretvorbo z uporabo ene izmed obstoječih funkcij. Za spodnji primer smo uporabili
funkcijo toDouble(), za pretvorbo Int vrednosti v Double [7]: val i: Int = 7
// Eksplicitna pretvorba Int v Double
val d: Double = i.toDouble()
• Znakov (Char) ne moremo direkto uporabiti kot števila. Lahko jih pa pretvorimo v
število z uporabo funkcije toInt(), kot prikazuje spodnji primer [7]: val c: Char = 'c'
val i: Int = c.toInt()
• Logični operatorji v programskem jeziku Java in Kotlin se malce razlikujejo.
Podrobno si bomo pogledali razliko med logičnima operatorjema »in« in »ali«. V
programskem jeziku Java uporabljamo oznake za operatorje, v programskem
jeziku Kotlin pa napišemo kar z besedo [7].
11
// Java
int operatorAli = FLAG1 | FLAG2;
int operatorIn = FLAG1 & FLAG2;
// Kotlin
val operatorAli = FLAG1 or FLAG2
val operatorIn = FLAG1 and FLAG2
• Do niza znakov (String) lahko dostopamo kot do tabele in posledično se lahko
sprehodimo po njej z uporabo for zanke. V programskem jeziku Kotlin bi zgornji
primer izgledal takole [7]: val s = "Primer"
val c = s[2] // dobimo črko 'i'
// sprehod čez String
val s = "Primer"
for (c in s) {
print(c)
}
4.2 Spremenljivke
V programskem jeziku Kotlin lahko določimo, ali so spremenljivke spremenljive (z uporabo
besede var) ali pa so nespremenljive oz. konstantne spremenljivke (z uporabo besede
val). Podobno v programskem jeziku Java uporabljamo besedo final pred nespremenljivo
spremenljivko. Nespemenljivost je pomemben princip (koncept) v programskem jeziku
Kotlin in v ostalih modernih programskih jezikih [7].
Nespremenljiv objekt je objekt, ki mu ne moremo spremeniti stanja po njegovi
inicializaciji. Če potrebujemo spremenjeno stanje, moramo narediti nov objekt. To naredi
programsko opremo bolj robustno in predvidljivo. V programskem jeziku Java je večina
objektov spremenljivih, kar pomeni, da jih lahko spreminjamo kjerkoli, imamo pa dostop
in s tem vplivamo na celotno aplikacijo [7].
Ker se nespremenljivi objekti ne morejo spremeniti, so zato tudi varni pred nitmi in zanje
ne potrebujemo posebnega nadzora, saj dobijo vse niti enak objekt [7].
Način našega razmišljanja se malce spremeni, če želimo v programskem jeziku Kotlin
izkoristiti nespremenljivost. Ključni prncip je, da uporabimo besedo val, kjerkoli je
12
mogoče. Seveda bodo primeri (še posebej v Androidu), kjer tega ne bo mogoče narediti.
Še ena dobra stvar je, da ni potrebno določiti tipa spremenljivke, saj ga spremenljivka
sama ugotovi iz vrednosti. To je zelo dobro, saj naredi kodo bolj berljivo in omogoča
hitrejše spreminjanje. Spodaj si lahko pogledamo nekaj primerov v programskem jeziku
Kotlin [7]:
val s = "Example" // String
val i = 23 // Int
val actionBar = supportActionBar // ActionBar
4.3 Inicializacija razreda
Razredi v programskem jeziku Kotlin imajo enostavno sintakso, ampak je vseeno malce
drugačna od tiste, ki smo jo navajeni v Javi. Poglejmo enostaven primer razreda v
programskem jeziku Kotlin [7]:
class MainActivity {
}
Kot vidimo zgoraj, se osnovni del sintakse ne razlikuje od tiste, ki smo jo navajeni iz
programskega jezika Java. V programskem jeziku Kotlin imajo razredi edinstven privzeti
konstruktor. Za posebne primere lahko imamo tudi dva konstruktorja, ampak v večini
primerov nam zadošča le eden. Takoj za imenom razreda sledita oklepaja, znotraj
katerega se nahajajo parametri. Pozorni moramo biti, da najprej napišemo ime
spremenljivke, šele nato njen tip. Zavitih oklepajev ne uporabljamo, če razred ne vsebuje
nobene vsebine, kot prikazuje spodnji primer [7]:
class Oseba(ime: String, priimek: String)
Verjetno se sprašujete, kje se nahaja telo konstruktorja. Lahko ga za zapišemo znotraj init
bloka:
public class Oseba(ime: String, priimek: String) {
init {
...
}
}
Poglejmo zgornji primer še v programskem jeziku Java:
class Oseba {
public Oseba(String ime, String priimek) {
}
}
13
Vidimo, da je razlika predvsem v izgledu konstruktorja, kot tudi vrstnem redu zapisovanja
parametrov znotraj oklepajev. V programskem jeziku Java najprej napišemo tip
spremenljivke, šele nato ime.
4.4 Funkcije
Sintaksa za funkcije se razlikuje med programskima jezikoma Java in Kotlin. Razliko si
bomo pogledali na preprostem primeru. Napišimo funkcijo, ki sprejme dva parametra tipa
Integer in vrne njihovo vsoto. Poglejmo, kako izgleda zgornji primer v programskem jeziku
Java:
public int vsota(int st1, int st2) {
return st1 + st2;
}
V programskem jeziku Kotlin pa je drugače:
fun vsota(st1: Int, st2: Int): Int {
return st1 + st2
}
V programskem jeziku Kotlin nam ni treba pred začetkom funkcije pisati public, saj je
funkcija samodejno vidna povsod, razen če seveda ne napišemo private. Nato vedno
napišemo rezervirano besedo fun, da vemo, da gre za funkcijo oz. da jo deklariramo.
Naslednja stvar, ki jo napišemo, ni tip, ki ga funkcija vrača, ampak ime funkcije (v našem
primeru vsota). Znotraj oklepaja napišemo parametre, ki jih funkcija sprejema (ime in šele
nato tip spremenljivke). V programskem jeziku Kotlin funkcije vedno vračajo vrednost, ki
jo določimo, v nasportnem primeru vračajo Unit. Unit je kot void v programskem jeziku
Java, le s to razliko, da je objekt. Seveda lahko določimo, da funkcija vrača katerikoli tip (v
našem primeru Int). Znotraj zavitih oklepajev pa sledi klasična koda, ki jo mora funkcija
izvesti.
14
4.5 Lastnosti
Lastnosti v programskem jeziku Kotlin so ekvivalentne poljem v programskem jeziku Java
in omogočajo dodatne operacije. Lastnosti opravijo enako delo kot polja, poleg pa imamo
še get in set metode. Poglejmo razlike na naslednjem primeru [7]:
public class Oseba {
private String ime;
public String getIme() {
return ime;
}
public void setIme(String ime) {
this.ime = ime;
}
}
...
Oseba oseba = new Oseba();
oseba.setIme("Janez");
String ime = oseba.getIme();
Zgornja koda je napisana v programskem jeziku Java ter omogoča varno dostopanje in
spreminjanje polja. V programskem jeziku Kotlin potrebujemo samo lastnosti [7]:
class Oseba {
var ime: String = ""
}
...
val oseba = Oseba()
oseba.ime = "Janez"
val ime = oseba.ime
Če ni drugače, določeno lastnost uporablja privzete set in get metode. Seveda pa lahko te
metode prilagodimo svojim potrebam, ne da spreminjamo obstoječe kode [7]:
class Oseba {
var ime: String = ""
get() = field.toUpperCase()
set(value) {
field = "Ime: $value"
}
}
15
4.6 Zanke
Sintaksa za osnovne for zanke je v programskem jeziku Kotlin drugačna od tistih, ki smo
jih vajeni pisati v Javi in ostalih programskih jezikih kot npr. C++ in C#. Pod osnovne for
zanke mislimo tiste, ki jih uporabljamo npr. za izpis števil od 0 do 10 itd. Poglejmo si
enostaven primer izpisa prvih 10 števil v programskem jeziku Java:
// Izpiše 0 1 2 3 4 5 6 7 8 9 10
for(int x = 0; x < 11; x++){
System.out.print( x );
}
Enako for zanko bi v programskem jeziku Kotlinu napisali takole:
// Izpiše 0 1 2 3 4 5 6 7 8 9 10
for (x in 0..10) {
print(x)
}
V programskem jeziku Kotlin ni treba določiti tipa spremenljivke, ampak samo določimo
ime spremenljivke (v našem primeru x) ter določimo interval izvajanja (od 0 do 10 oz.
0..10). Zapis se malce spremeni, če želimo v programskem jeziku Kotlin izpisati vsako
drugo število na intervalu od 0 do 10.
// Izpiše 0 2 4 6 8 10
for (x in 0..10 step 2) {
print(x)
}
Vse, kar smo dodali, je funkcija step() in število 2. Število, ki ga dodamo poleg besede
step, nam pove, za koliko bomo povečali spremenljivko po vsaki iteraciji, v našem primeru
spremenljivko x.
Oba zgornja primera v programskem jeziku Kotlin sta povečevala vrednost spremenljivke,
če jo želimo zmanjševati oz. izpisati števila v obratnem vrstnem redu, moramo uporabiti
funkcijo downTo(). Poglejmo si spodnji primer v programskem jeziku Kotlin:
// Izpiše 10 9 8 7 6 5 4 3 2 1 0
for (x in 10 downTo 0) {
print(x)
}
Vse, kar moramo narediti je, da napišemo začetno vrednost (v našem primeru 10) in
poleg besede downTo napišemo število, do katerega želimo izvajati funkcijo (v našem
primeru 0). Tudi v zgornji for zanki lahko uporabimo funkcijo step() in povečamo korak
zmanjševanja, kot prikazuje spodnji primer v programskem jeziku Kotlin:
16
// Izpiše 10 8 6 4 2 0
for (x in 10 downTo 0 step 2) {
print(x)
}
For zanki, s katerima se premikamo po seznamih, sta si v programskih jezikih Java in Kotlin
precej podobni. Imamo seznam imen, ki vsebuje štiri imena, in jih želimo izpisati tako v
programskem jeziku Java kot v programskem jeziku Kotlin. Poglejmo kodo v programskem
jeziku Java:
String [] imena = {"Ana", "Žan", "Metka", "Janez"};
// Izpiše Ana Žan Metka Janez
for( String ime : imena ) {
System.out.print( ime );
}
Ustvarili smo seznam z imeni in v for zanki ustvarili spremenljivko, ime tipa String, ki jo
uporabimo za izpis vseh imen v seznamu. V programskem jeziku Kotlin bi zgornji primer
izgledal takole:
val imena = listOf("Ana", "Žan", "Metka", "Janez")
// Izpiše Ana Žan Metka Janez
for (ime in imena) {
print(ime)
}
Poleg tega, da se drugače inicializira seznam, lahko opazimo tudi, da je drugačna sintaksa
for zanke. V tem primeru ni treba spremenljivki določiti tipa, ampak samo ime
spremenljivke (v našem primeru »ime«) in dvopičje (»:«), ki ga imamo v programskem
jeziku Java, tukaj zamenjamo z »in«.
While zanke so popolnoma enake tako v programskem jeziku Java kot v programskem
jeziku Kotlin.
17
4.7 Delo s seznami
Zelo pogosto se zgodi, da moramo narediti zahtevne operacije nad podatkovnimi
seznami. Recimo, da imamo seznam študentov, iz katerega moramo pridobiti tri študente
z oceno A (0) in dva študenta z oceno B (1). Poglejmo si rešitev v programskem jeziku
Kotlin [8]:
var students = listOf(Student("Žan", 0), Student("Ana", 2),
Student("Metka", 1), Student("Janez", 0), Student("Alenka", 0))
var firstList = students.filter { it.mark == 0 }.take(3)
var secondList = students.filter { it.mark == 1 }.take(2)
Tako bi nalogo rešili v programskem jeziku Java [8]:
ArrayList<Student> students = new ArrayList<Student>() {{
add(new Student("Žan", 0));
add(new Student("Ana", 2));
add(new Student("Metka", 1));
add(new Student("Janez", 0));
add(new Student("Alenka", 0));
}};
ArrayList<Student> firstList = new ArrayList<>();
ArrayList<Student> secondList = new ArrayList<>();
for (Student student: students) {
boolean isFirstFilled = firstList.size() >= 3;
boolean isSecondFilled = secondList.size() >= 2;
if (isFirstFilled && isSecondFilled) break;
int mark = student.getMark();
if (mark == 0 && !isFirstFilled) {
firstList.add(student);
} else if (mark == 1 && !isSecondFilled) {
secondList.add(student);
}
}
To je samo primerjava, kako delamo s seznami v programskem jeziku Java in
programskem jeziku Kotlin. Si lahko predstavljate, kakšna bi bila razlika, če bi delali s
seznami na velikem projektu [8]?
18
4.8 Povezovanje komponent
Večino programerjev, ki razvijajo Android aplikacije s programskim jezikom Java, moti, da
morajo neprestano deklarirati spremenljivke za dostop do vsake komponente, ki jo
potrebujejo (view binding). Če uporabljamo programski jezik Kotlin, lahko pozabimo na
povezovanje komponent. Ni potrebno več pisati tolikšnih dodatnih spremenljivk, saj lahko
direktno dostopamo do komponent preko unikatnega identifikatorja, ki smo ga določili v
datoteki XML. Poglejmo si, kako bi v programskem jeziku Java implementirali, da ko
uporabnik klikne na gumb, se izpiše besedilo »Kliknili ste na gumb« [8]:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button gumb = (Button) findViewById(R.id.gumb);
final TextView besedilo = (TextView)
findViewById(R.id.besedilo);
gumb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
besedilo.setText("Kliknili ste na gumb");
}
});
}
}
Sedaj pa rešimo problem v programskem jeziku Kotlin [8]:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState:
PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.activity_main)
gumb.setOnClickListener { besedilo.text = "Kliknili ste na
gumb" }
}
}
V programskem jeziku Kotlin je stvar enostavnejša. V bistvu se metoda findViewById() še
zmeraj uporablja, ampak je ni treba napisati razvijalcem, saj jo Kotlin napiše namesto njih
[8].
19
4.9 Vmesniki
Vmesniki (interface) v programskem jeziku Kotlin so močnejši od tistih, ki jih najdemo v
Javi 7. Lahko jih uporabljamo tudi na tak način, kot smo jih navajeni uporabljati v
programskem jeziku Java. Predstavljajte si, da imamo nekaj živali in nekatere od njih lahko
letijo. Vmesnik za živali, ki lahko letijo, bi izgledal tako [7]:
interface FlyingAnimal {
fun fly()
}
Tako ptice kot netopriji lahko letijo s premikanjem kril. Torej, naredimo dva razreda –
Ptica oz. Bird in Netopir oz. Bat [7]:
class Ptica : FlyingAnimal {
val wings: Wings = Wings()
override fun fly() = wings.move()
}
class Bat : FlyingAnimal {
val wings: Wings = Wings()
override fun fly() = wings.move()
}
Ko dva razreda dedujeta iz enega vmesnika, si zelo pogosto delita isto implementacijo.
Vmesniki v Javi 7 lahko samo definirajo obnašanje, ampak ga ne morejo implementirati
[7].
Na drugi strani pa so vmesniki v programskem jeziku Kotlin zmožni implementirati
funkcije. Edina razlika je v tem, da bo razred odgovoren za shranjevanje lastnostni
vmesnika. V programskem jeziku Kotlin lahko naredimo, da vmesnik implementira
funkcijo fly [7]:
interface FlyingAnimal {
val wings: Wings
fun fly() = wings.move()
}
Sedaj morata razreda prepisati lastnost:
class Bird : FlyingAnimal {
override val wings: Wings = Wings()
}
class Bat : FlyingAnimal {
override val wings: Wings = Wings()
}
20
Sedaj lahko tako ptice kot netopirji letijo:
val bird = Bird()
val bat = Bat()
bird.fly()
bat.fly()
21
5 PREDNOSTI PROGRAMSKEGA JEZIKA KOTLIN
Poglejmo si, kakšne in katere so prednosti Kotlina v primerjavi z Javo 6 [7]?
• Večja izrazitost: to je ena izmed pomebnejših kvalitet. Veliko več lahko napišemo z
manj kode [7].
• Varnost: Kotlin je null varen, kar pomeni, da morebitne ničelne vrednosti
obravnavamo v času prevajanja, da bi preprečili napake v času izvajanja. Objekt
lahko ima ničelno vrednost, vendar moramo to eksplicitno navesti in pred njegovo
uporabo tudi preveriti. S tem bomo prihranili veliko časa, saj ne bo potrebno
razhroščevati in popravljati neveljavnih napak [7].
• Funkcionalnost: Kotlin je v bistvu objetkno orientiran in ni čisti funkcijski
programski jezik. Kot večina programskih jezikov tudi tukaj najdemo veliko
konceptov funkcijskega programiranja kot npr. lambda izrazi, ki jih uporabljamo za
lažje reševanje problemov. Še ena dobra lastnost je način reševanja problemov z
zbirkami [7].
• Možnost razširitvenih funkcij: to pomeni, da lahko katerikoli razred razširimo z
novimi lastostmi, tudi če nimamo dostopa do izvorne kode [7].
• Interoperabilnost: še naprej lahko uporabljamo večino knjižnic in programske
kode, napisane v Javi, in sicer zaradi odlične interoperabilnosti med obema
jezikoma. Možno je narediti mešani projekt, ki bo vseboval tako Kotlin kot Java
datoteke [7].
5.1 Izrazitost
Ena izmed večjih prednosti programskega jezika Kotlin je ta, da lahko z manj kode
naredimo več. Če napišemo manj kode, potem tudi posledično naredimo manj napak med
samim pisanjem [8].
public final class Oseba {
private String ime;
private int starost;
private float visina;
public Oseba(String ime, int starost, float visina) {
this.ime = ime;
this.starost = starost;
this.visina = visina;
}
public Oseba(String ime, int starost) {
this.ime = ime;
this.starost = starost;
this.visina = 1.8f;
22
}
public String getIme() {
return ime;
}
public void setIme(String ime) {
this.ime = ime;
}
public int getStarost() {
return starost;
}
public void setStarost(int starost) {
this.starost = starost;
}
public float getVisina() {
return visina;
}
public void setVisina(float visina) {
this.visina = visina;
}
@Override
public String toString() {
return "Oseba{" +
"ime='" + ime + '\'' +
", starost=" + starost +
", visina=" + visina +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Oseba Oseba = (Oseba) o;
if (starost != Oseba.starost) return false;
if (Float.compare(Oseba.visina, visina) != 0) return false;
return ime != null ? ime.equals(Oseba.ime) : Oseba.ime == null
}
@Override
public int hashCode() {
int result = ime != null ? ime.hashCode() : 0;
result = 31 * result + starost;
result = 31 * result + (visina != +0.0f ?
Float.floatToIntBits(visina) : 0);
return result;
}
}
23
Zgornji primer razreda je napisan v programskem jeziku Java. Naredili smo razred Oseba z
lastostmi, ime, starost in velikost. Težko je gledati toliko programske kode, ko ugotoviš,
kako malo naredi. Spodaj vidimo še enak primer razreda, napisanega v programskem
jeziku Kotlin [8]:
data class Oseba(var ime: String,
var starost: Int,
var visina: Float = 1.8f)
Kot je opazno, je razlika v številu vrstic, v primerjavi s programskim jezikom Java,
ogromna. Samodejno dobimo funkcije za nastavljanje in pridobivanje lastnosti (set in get
metode), za Hash vrednosti, za izpis in kopiranje. Če bi radi kakšno izmed funkcij
spremenili, jo lahko prepišemo oz. dopolnimo po naših željah, ampak v večini primerov
nam zadostujejo privzete funkcije [8].
5.2 Null varnost
Null varnost je ena izmed najbolj zanimivih lastnosti programskega jezika Kotlin, seveda
ob predpostavki, da smo prej uporabljali Javo 7. V programskem jeziku Java lahko
naredimo naslednje [7]:
Forecast forecast = null;
forecast.toString();
Zgornja koda se bo brez težav prevedla in mogoče bomo dobili opozorilo od IDE. Ko bomo
kodo pognali, bomo seveda dobili napako »NullPointerException«. To lahko postane zelo
nevarno. Tudi če mislimo, da imamo vse pod kontrolo, bomo začeli izgubljati nadzor, ko
bo koda začela sunkovito rasti. Končamo z veliko »NullPointerException« napakami ali pa
imamo preverjane vrednosti spremenljivk (verjetno imamo mešanico obojega) [7].
Večina modernih programskih jezikov rešuje to težavo na edinstven način. Programski
jezik Kotlin uporablja vprašaje za indentifikacijo ničelnih tipov, podobno kot programski
jezik Swift (programski jezik za razvoj iOS aplikacij). Ker je v programskem jeziku Kotlin vse
objekt (tudi javanski primitivni tipi), pomeni, da lahko imajo vrednost null. Potem lahko
imamo tudi ničelne spremenljivke tipa integer [7]:
val a: Int? = null
24
Dokler ne preverimo vrednosti, ne moremo uporabljati ničenih tipov, npr. spodnja koda
se ne bo prevedla [7]:
val a: Int? = null
a.toLong()
Koda se ne prevede, saj bi lahko spremenljivka »a« imela vrednost null (v našem primeru
jo tudi ima), in prevajalnik se tega zaveda. Dokler ne preverimo, ali ima spremenljivka
vrednost null, je ne bomo mogli uporabljati [7].
V nadaljevanju pride do izraza še ena funkcija, imenovana smart cast, ki jo najdemo v
programskem jeziku Kotlin. Pomeni, da od trenutka, ko smo preverili vrednost objekta, se
objekt pretvori v neničelen tip. Poglejmo primer [7]:
val a: Int? = null
...
if (a != null) {
a.toLong()
}
Znotraj pogojnega stavka if, se Int? pretvori v Int, zati ni potrebno več preverjati njegove
vrednosti. Ko pa enkrat zapustimo if stavek, bomo morali zopet preveriti vrednost
objekta. To seveda deluje samo, če gre za spremenljivko, ki ji ne more druga nit
spremeniti vrednosti, saj bi se lahko zgodilo, da objekt postane null. Koda deluje, če
imamo val spremenljivko oz. lokalno (val ali var) spremenljivko [7].
Zgornji primer nakazuje, da bomo imeli veliko dela s preverjanjem vrednosti objektov,
ampak temu ni tako, ker večino časa ne bomo potrebovali ničelnih objektov. Programski
jezik Kotlin pa ima tudi svoj mehanizem, ki olajša zadevo. Npr. zgornji primer lahko
poenostavimo tako [7]:
val a: Int? = null
...
a?.toLong()
Uporabljamo tako imenovani varni operator (safe call operator, napisan ?). Zgornja
vrstica kode se bo izvedla samo, če spremenljivka nima vrednosti null, v nasprotnem
primeru se ne bo zgodilo nič. Lahko zagotovimo alternativo za ničelne vrednosti s
pomočjo Elvis operatorja (?:) [7]:
val a: Int? = null
...
val myLong = a?.toLong() ?: 0L
25
Zgodili se bodo tudi primeri, kjer bomo zagotovo vedeli, da delamo z neničelnim
objektom. Takrat lahko prevajalnik prisilimo, da dela z neničelnim objektom, z uporabo !!
operatorja [7]:
val a: Int? = null
a!!.toLong()
Zgornja koda se bo brez težav prevedla, ampak se bo v času izvajanja ustavila. Moramo
zagotoviti, da bomo operator uporabljali samo v posebnih primerih. Večinoma lahko
uporabimo tudi alternativne rešitve. Koda polna !! pomeni, da nekaj ni prav narejeno [7].
5.3 Enostavno učenje
Tudi brez predznanja je učenje programskega jezika Kotlin enostavnejše od učenja
programskega jezika Java. Če želimo izdelati preprosto aplikacijo, ki seveda ni »Hello
world!«, potrebujemo samo nekaj ur. Poleg tega, če ste že kdaj razvijali v C# ali Javi, ne
boste imeli težav pri prehodu na programski jezik Kotlin. JetBrain se je zelo posvetil
dokumentaciji in jo napisal tako, da bi osnove programskega jezika Kotlin brez težav
razumel tudi »osnovnošolec« [11].
5.4 Razširitvene funkcije
Programski jezik Java še vedno ne razmišlja o vpeljavi razširitvene funkcije (extension
functions). Po drugi strani boste razširitvene funkcije v programskem jeziku Kotlin zelo
veseli, če ste jo že prej uporabljali v C# ali Gosu. Razširitvena funkcija je tista, ki doda novo
obnašanje obstoječemu razredu, če nimamo izvorne kode tega razreda. V programskem
jeziku Java je to večinoma implementirano v utility razredih, ki vsebujejo niz statičnih
metod. Prednost uporabe razširitvenih funkcij v programskem jeziku Kotlin je v tem, da ni
treba pošiljati objekta kot parameter. Razširitvena funkcija se obnaša, kot da je del
razreda [7].
Kot primer lahko naredimo toast funkcijo, ki ji kot parameter ne bo treba dati konteksta
(»context«) [7]:
fun Context.toast(message: CharSequence, duration: Int =
Toast.LENGTH_SHORT) {
Toast.makeText(this, message, duration).show()
26
}
Zgornjo funkcijo lahko uporabimo znotraj kateregakoli okna [7]:
toast("Hello world!")
toast("Hello world!", Toast.LENGTH_LONG)
Razširitvene funkcije lahko deklariramo v katerikoli datoteki, priporočjivo je, da ustvarimo
datoteke, ki vsebujejo niz sorodnih funkcij [7].
5.5 Interoperabilnost
Povezljivost med programskima jezikoma Java in Kotlin je zelo dobra lastnost za začetnike
v programskem jeziku Kotlin. V istem projektu lahko imamo tako Kotlin kot Java datoteke
brez tveganja, da bi dobili kakšno napako. Kotlin knjižnice lahko brez težav uporabljamo v
javanskih projektih in obratno. To, da lahko imamo obe vrsti datotek v enem projektu, je
zelo dobra lastnost, saj nam ni potrebno obstoječega projekta v celoti prevesti oz. začeti
čisto od začetka. Uporabniki, ki prvič uporabljajo programski jezik Kotlin, lahko enostavno
začnejo programirati v novem programskem jeziku na določenem delu projekta in kasneje
seveda združijo javanske datoteke s Kotlinom. Ko bomo združevali datoteke, je
priporočljivo, da združujemo po eno datoteko naenkrat, in preverjamo, če vse deluje
tako, kot mora. Zmožnost kombiniranja z Javo je ključnega pomena, saj lahko preizkusimo
programski jezik brez dodatnega tveganja [12].
5.6 Pametno pretvarjanje
Nekaj podatkov smo že napisali v prejšnjem poglavju (5.2). V programskem jeziku Java
moramo pogosto preverjati tip objekta in ga šele nato pretvoriti, tudi tam, kjer je že
jasno, da ga lahko pretvorimo [13].
Kotlinovo pametno pretvarjanje (smart cast) lahko upravlja ponavljajoče pretvarjanje za
nas in nam ni treba pretvarjati objekta znotraj pogojnega stavka, če smo predhodno
preverili tip s pomočjo is operatorja. Npr.: pri spodnjem primeru prevajalnik ve, da je
pretvarjanje varno [13]:
27
if (hello is String) {
printString(hello)
}
5.7 Funkcije višjega reda in lambda izrazi
Še ena izmed Kotlinovih glavnih lastnosti so funkcije višjega reda. Če ste seznanjeni z
Javascriptom ali C#, potem verjetno veste vse o teh funkcijah. Funkcije višjega reda
sprejmejo funkcijo kot parameter ali pa jo vračajo. To se zelo uporablja pri tako
imenovanih callback funkcijah. Lahko naredimo funkcijo, ki vrača dve vrednosti, eno za
uspešno izvedbo, in eno za napako. V programskem jeziku Kotlin bi to bile funkcije z
dvema parametroma, v Javi pa bi morali slediti vzorcu, kjer imamo vmesnik, ki mu
pošljemo instanco, ki implementira ta vmesnik (veliko več kode). Funkcije lahko
shranjujemo v spremenljivkah za kasnejšo uporabo, pošiljanje naokoli … Če funkcija ni
deklarirana in je takoj poslana kot izraz (expression), imenujemo to labmda izraz ali
anonimna funkcija. V Javi 8 so dodali podporo za lambda izraze, ampak če razvijate
Android aplikacije, ste obtičali na Javi 7. To je zelo pomemben razlog, zakaj je programski
jezik Kotlin tako dobra alternativa programskemu jeziku Java, če ravijamo za Android [14].
28
6 PREDNOSTI PROGRAMSKEGA JEZIKA JAVA
Čeprav ima programski jezik Kotlin zelo veliko uporabnih karakteristik, obstajajo še vedno
primeri, kjer je programski jezik Java bolj priporočljiv. Poglejmo jih bolj podrobno [11]:
• Kompaktnejše aplikacije: praksa je pokazala, da aplikacije, ki so izdelane s
programskim jezikom Kotlin, zavzamejo več prostora v primerjavi z aplikacijami,
razvitimi v programskem jeziku Java. To pomeni, da se lahko aplikacije z zahtevno
procesorsko nalogo nalagajo zelo počasi na mobilnih napravah, ki imajo slabše
specifikacije. Prepričani smo, da ta slabost ne bo dolgo trajala in bo odpravljena v
novih verzijah programskega jezika Kotlin [11].
• Hitrejše prvo prevajanje: druga ne tako velika prednost programskega jezika Java
v primerjavi s programskim jezikom Kotlin je čas prvega prevajanja z Gradlom (vsi
vemo, kako boleče je, če traja prevajanje predolgo časa). Po raziskavah naj bi
programski jezik Java imel 13 % hitrejši prevajalnik od programskega jezika Kotlin
(v povprečju 14.1 sekund proti 16.5 sekund, Slika 6.1). Če smo povsem iskreni, je
Gradl znan po tem, da je zelo počasen [11].
Slika 6.1: Primerjava časa prevajanja z Gradlom v obeh programskih jezikih (Vir:https://medium.com/keepsafe-engineering/kotlin-vs-java-compilation-speed-
e6c174b39b5d)
• Večja skupnost in več dostopne pomoči: ker je programski jezik Kotlin dokaj nov,
ima zelo majhno skupnost uporabnikov v primerjavi s programskim jezikom Java.
Za programski jezik Java imamo veliko število primerov uporabe, objav na blogu,
dokumentacije različnih uporabnikov, večjo podporo skupnosti npr. na
29
StackOverflow itd. Trenutno imamo na StackOverflow 4.600 objav v zvezi s
Kotlinom, in preko 1.000.000 objav, ki vsebujejo besedo Java [15].
• Možnost pretvorbe javanske kode v Kotlin: pretvorba iz Java datoteke v Kotlin je
povsem enostavna. Naprej moramo odpreti Java datoteko, ki jo želimo pretvoriti.
Nato v zgornji vrstici izberemo Code in kliknemo na Convert Java File to Kotlin File
(Slika 6.2).
Slika 6.2: Pretvroba javanske kode v Kotlin
Pri pretvorbi moramo biti pozorni na to, da se bo rezultat pretvorbe shranil v enako
datoteko. Zaradi tega je bolje, če si prekopiramo javansko kodo v novo datoteko in tam
izvedemo spremembo v programski jezik Kotlin. To nam omogoča lažjo postopno
pretvorbo velikih datotek v programski jezik Kotlin, ne da bi vplivali na delovanje
aplikacije. Pretvroba v programski jezik Kotlin ni popolna. Osnovne razrede in funkcije bo
pretvoril brez napak, ampak pri bolj kompleksnih razredih pa nastanejo napake, ki jih
moramo ročno popraviti, kot prikazuje spodnji primer kode:
30
//del kode iz Java datoteke katero bomo pretvorili
public static DataAll load(File file) {
...
FileInputStream fstream = new FileInputStream(file);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader( new InputStreamReader(in));
StringBuffer sb = new StringBuffer();
String strLine;
while ((strLine = br.readLine()) != null) {
sb.append(strLine).append('\n');
}
Gson gson = new GsonBuilder().setPrettyPrinting().create();
DataAll dataAll = gson.fromJson(sb.toString(), DataAll.class);
return dataAll;
...
}
//pretvorjeni del kode v Kotlin datoteki
fun load(file: File): DataAll? {
...
val fstream = FileInputStream(file)
val `in` = DataInputStream(fstream)
val br = BufferedReader(InputStreamReader(`in`))
val sb = StringBuffer()
var strLine: String
while ((strLine = br.readLine()) != null) { //napaka
sb.append(strLine).append('\n')
}
val gson = GsonBuilder().setPrettyPrinting().create()
val dataAll = gson.fromJson<DataAll>(sb.toString(),
DataAll::class.java!!)
return dataAll
...
}
//popravljeni del kode v Kotlin datoteki
fun load(file: File): KotlinDataAll? {
..
val fstream = FileInputStream(file)
val string = fstream.bufferedReader().use(BufferedReader::readText)
val gson = GsonBuilder().setPrettyPrinting().create()
val data = gson.fromJson(string, DataAll::class.java)
return data
..
}
31
7 MOBILNA APLIKACIJA JAZGOBAR
V sklopu zaključnega dela smo izdelali mobilno aplikacijo za Android operacijski sistem.
Aplikacijo smo izdelali tako v programskem jeziku Java kot v programskem jeziku Kotlin,
saj smo želeli prikazati razlike programskih jezikov na praktičnem primeru.
7.1 Opis ideje
Mobilna aplikacija JazGobar (Slika 7.1) je namenjena vsem gobarjem. Aplikacija omogoča,
da na enostaven način dodamo lokacijo gob, tako da slikamo gobo, poimenujemo dodano
lokacijo in označimo, katere vrste gob se nahajajo na dani lokaciji. Ob dodajanju gobe
aplikacija samodejno pridobi tudi podatke o lokaciji in o trenutnih vremenskih razmerah.
Uporabniške podatke, ki jih pridobimo o vremenu v času nabiranja gob, kasneje
obdelamo z evolucijskim algoritmom, ki nas glede na vreme obvesti, kdaj bi se lahko
pojavile nove gobe.
Slika 7.1: Ikona aplikacije JazGobar
V aplikacijo se lahko prijavimo s pomočjo Facebook računa ali pa si ustvarimo svoj račun
in se kasneje z njim prijavimo. Aplikacija ima zemljevid, kjer je označena naša trenutna
lokacija in lokacija vseh dodanih gob. V seznamu imamo prikazane vse naše dosedanje
lokacije gob, ki jih lahko urejamo glede na oddaljenost od naše trenutne lokacije in vrsto
gobe. Uporabniki lahko ocenujejo slike ostalih uporabnikov glede na to, ali se na dani sliki
res nahajajo gobe, ki so označene. Uporabnik, ki je pridobil dovolj točk z ocenjevanjem,
32
postane moderator, kar pomeni, da on dokončno odloči, ali se na slikah s slabo oceno res
nahajajo označene gobe.
7.2 Implementacija
Najprej bomo opisali izgradnjo osnovnega uporabniškega vmesnika mobilne aplikacije.
Nato sledi opis izdelave logike aplikacije. Primerjava je opravljena tako, da opišemo
rešitev v programskem jeziku Java, sledi implementacija v programski jezik Kotlin s
pomočjo vgrajenega prevajanika v Android Studiu, in seveda popravilo napak, ki so
nastale ob prevajanju.
7.3 Uporabniški vmesnik
Uporabniški vmesnik je enak tako v mobilni aplikaciji, ki smo jo izdelali v programskem
jeziku Java, kot v tisti, ki smo jo izdelali v Kotlinu, saj imata identične datoteke XML.
Uporabniški vmesnik se izdeluje s pomočjo kode XML. Poglejmo si spodnji primer kode
XML za glavno okno aplikacije:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline3"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.9" />
<android.support.v7.widget.RecyclerView
android:id="@+id/myrecycleview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/btnOdjava" />
33
<Button
android:id="@+id/btnMapa"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="0dp"
android:background="@drawable/map_icon"
android:onClick="openMap"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline3"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintRight_toLeftOf="@+id/guideline10"
android:layout_marginRight="10dp"
app:layout_constraintHorizontal_bias="0.0" />
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline10"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.2" />
</android.support.constraint.ConstraintLayout>
Pozitivna stran je, da ni teba pisati kode XML, saj lahko vse naredimo z miško. Preprosto
na delovno površino povlečemo komponente oz. elemente, ki jih v določenem oknu
potrebujemo, in koda XML se sama ustvarja v ozadju. Lastnostni komponent (velikost,
vsebina, odmik …) določimo v meniju na desni strani (Slika 7.2).
Slika 7.2: Izgradnja uporabniškega vmesnika
34
Levo okno nam prikazuje trenutni izgled uporabniškega vmesnika, desno (modro okno) pa
uporabljamo za določanje lokacije komponente na oknu in njene odvistnosti od drugih
komponent. S tem dosežemo, da bo naš uporabniški vmesnik enak na vseh napravah in
prilagodljiv ne glede na velikost mobilnega zaslona, na katerem se bo aplikacija izvajala.
7.4 Povezava elementov s programsko kodo
Elemente, ki jih ustvarimo v datoteki XML, je potrebno povezati s programsko kodo, da
lahko opravijo svojo nalogo. Vsem elementom moramo podati ID oz. unikatno ime, preko
katerega se povežemo v programski kodi. V programskem jeziku Java moramo za
povezavo uporabiti posebno metodo findViewById, v programskem jeziku Kotlin pa lahko
kar direktno uporabimo ID objekta brez uporabe findViewById.
• Primer v programskem jeziku Java public class ActivityLogin extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
LoginButton
loginButton=(LoginButton)findViewById(R.id.fb_login_bn);
EditText etUserName = (EditText)
findViewById(R.id.etUserNameR);
EditText etPassword = (EditText)
findViewById(R.id.etPasswordR);
Button btnLogin = (Button) findViewById(R.id.btnLogin);
TextView tvRegister = (TextView) findViewById(R.id.tvRegister);
...
}
...
tvRegister.setText("Register");
}
• Primer v programskem jeziku Kotlin class KotlinActivityLogin : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.kotlin_activity_login)
...
}
...
tvRegister.text = "Register"
}
35
7.5 Meni
Za izvedbo različnih funkcionalnosti (nastavitve, urejanje seznama lokacij gob …) smo
implementirali meni. Najprej smo naredili datoteko XML, kjer smo definirali, katere
funkcije bo meni vseboval. Nato smo znotraj okna dodali metodo onCreateOptionsMenu,
ki ustvari meni iz podane datoteke XML. Da pa se nekaj izvede ob pritisku na gumb, smo
implementirali metodo onOptionsItemSelected.
• Metoda onOptionsItemSelected v programskem jeziku Java @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
startActivity(new Intent(this,ActivityMySettings.class));
return true;
case R.id.action_slike_gob:
startActivity(new Intent(this,ActivitySlikeGob.class));
return true;
case R.id.action_galerija:
startActivity(new Intent(this,ActivityGalerija.class));
return true;
case R.id.action_sort:
app.sortChangeAndUpdate();
mAdapter.notifyDataSetChanged();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
• Metoda onOptionsItemSelected v programskem jeziku Kotlin override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_settings -> {
startActivity(Intent(this,
KotlinActivityMySettings::class.java))
return true
}
R.id.action_slike_gob -> {
startActivity(Intent(this,
KotlinActivitySlikeGob::class.java))
return true
}
R.id.action_galerija -> {
startActivity(Intent(this,
KotlinActivityGalerija::class.java))
return true
}
R.id.action_sort -> {
app?.sortChangeAndUpdate()
mAdapter!!.notifyDataSetChanged()
return true
}
36
else -> return super.onOptionsItemSelected(item)
}
}
7.6 Eventbus
Eventbus je odprtokodna knjižnica za Android, ki se uporablja za lažjo komunikacijo med
razredi. Deluje tako (Slika 7.3), da se razredi, ki potrebujejo določeni podatek, preko
metode Subscribe naročijo na Eventbus in tako pridobijo podatek takoj, ko se ta spremeni
oz. odvisno od načina uporabe. Naročnikom podatke pošilja Publisher preko post()
metode.
Slika 7.3: Delovanje EventBus-a ( Vir: http://greenrobot.org/eventbus/)
Svojo mobilno aplikacijo Eventbus smo uporabili za deljenje GPS lokacije med razredi. To
pomeni, da smo samo preko enega razreda pridobili GPS lokacijo in jo posredovali vsem
razredom, ki so se preko Evetbus-a naročili na ta dogodek. Najprej se moramo v funkciji
onResume registrirati na Eventbus.
• Registriranje na Eventbus v programskem jeziku Java public void onResume(){
super.onResume();
if (!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
...
}
• Registriranje na Eventbus v programskem jeziku Kotlin public override fun onResume() {
super.onResume()
if (!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this)
37
...
}
To posledično pomeni, da se v funkciji onStop moramo od Eventbus-a odjaviti.
• Odjava od Eventbus-a v programskem jeziku Java @Override
protected void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
• Odjava od Eventbus-a v programskem jeziku Kotlin override fun onStop() {
EventBus.getDefault().unregister(this)
super.onStop()
}
Na koncu smo morali samo še naročiti oz. implementirati metodo onMessageEvent, ki se
bo odzivala na novo prejeto GPS lokacijo. Samo tisti razredi, ki so registrirani in naročeni
na Eventbus, bodo v našem primeru obveščeni o spremembi lokacije.
• Naročanje na Eventbus v programskem jeziku Java @Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEventUpdateLocation event) {
Log.i("ActivityZacetna","MessageEventUpdateLocation ");
mLocation = event.getM();
}
• Naročanje na Eventbus v programskem jeziku Kotlin @Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: KotlinMessageEventUpdateLocation) {
Log.i("KotlinActivityZacetna", "KotlinMessageEventUpdateLocation ")
mLocation = event.m
}
7.7 Shranjevanje podatkov o uporabniku
Kot smo že omenili, se lahko v apliakcijo prijavimo s pomočjo Facebook računa oz. e-
poštnega naslova in gesla, ki smo ga določili ob registraciji. Ob prijavi si moramo
zapomniti nekaj podatkov, kot so: uporabniško ime, ime uporabnika, e-poštni naslov
uporabnika, pridobljeno število točk, način prijave ter, ali obstaja datoteka JSON na
mobilni napravi. Podatke si zapomnimo s pomočjo SharedPreferences API-ja, ki jih
zapišemo v datoteko. Shranimo lahko podatke osnovnega tipa, torej Boolean, String, Int,
Float, String Set in Long. Podatke shranjujemo s pomočjo SharedPreferences. Editor-ja, ki
mu podamo unikatno ime, preko katerega bomo dostopali do podatkov, in sam podatek,
ki ga želimo shraniti.
38
• Shranjevanje podatkov v SharedPreferences v programskem jeziku Java SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("user_id",user);
editor.putString("et_full_name",user);
editor.putString("et_email_address",mail);
editor.putString("et_score",score);
editor.putBoolean("basicLogin",true);
editor.putBoolean("fileExist",fileExist);
editor.commit();
• Shranjevanje podatkov v SharedPreferences v programskem jeziku Kotlin val sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(applicationContext)
with (sharedPreferences.edit()) {
putString("user_id", user)
putString("et_full_name", user)
putString("et_email_address", mail)
putString("et_score", score)
putBoolean("basicLogin", true)
putBoolean("fileExist", fileExist)
commit()
}
Nikoli, ko pišemo oz. shranjujemo podatke, ne smemo na koncu pozabiti klicati metode
commit(), ki shrani podatke v datoteko.
Ko želimo pridobiti podatke, je podobno. Najprej ustvarimo spremenljivko
SharedPreferences, preko katere dostopamo do podatkov s pomočjo prej določenega
unikatnega imena. Poleg imena pa moramo podati tudi privzeto vrednost, ki se nastavi
spremenljivki v primeru, da še ne obstaja.
• Pridobivanje podatkov iz SharedPreferences v programskem jeziku Java SharedPreferences sp =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String user_id = sp.getString("user_id",null);
• Pridobivanje podatkov iz SharedPreferences v programskem jeziku Kotlin val sp =
PreferenceManager.getDefaultSharedPreferences(applicationContext)
val user_id = sp.getString("user_id", null)
39
7.8 Dodajanje lokacij gob
Dodajanje lokacij gob je sestavljeno iz več postopkov. Prvi je, da se ob kliku na gumb za
dodajanje gob odpre novo okno s fotoaparatom. Da se to zgodi, moramo za gumb
implementirati metodo OnClickListener. Spodaj se ob kliku na gumb odpre okno za
dodajanje lokacije, če ima aplikacija pridobljeno lokacijo od mobilne naprave. Uporabili
smo objekt Intent, kjer podamo kot parameter kontekst trenutnega razreda, in kateri
razred oz. okno želimo prikazati. Poleg lahko pošljemo tudi podatke z metodo putExtra,
ampak to ni obvezno. Za prikaz novega okna kličemo metodo startActivity.
• Implementacija metode OnClickLIstener v programskem jeziku Java FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mLocation==null) {
Snackbar.make(view,
getResources().getText(R.string.add_new_location_no_location),
Snackbar.LENGTH_LONG).show();
}else {
Intent i = new Intent(getBaseContext(),
ActivityLocation.class);
i.putExtra(DataAll.LOKACIJA_ID,
ActivityLocation.NEW_LOCATION_ID);
startActivity(i);
}
}
});
• Implementacija metode OnClickLIstener v programskem jeziku Kotlin fab.setOnClickListener { view ->
if (mLocation == null) {
Snackbar.make(view,
resources.getText(R.string.add_new_location_no_location),
Snackbar.LENGTH_LONG).show()
} else {
val i = Intent(baseContext, KotlinActivityLocation::class.java)
i.putExtra(KotlinDataAll.LOKACIJA_ID, "NEW_LOCATION")
startActivity(i)
}
}
Če naredimo fotografijo in označimo, da smo z njo zadovoljni, se nam prikaže okno, kjer
poimenujemo novo lokacijo in označimo, katera vrsta oz. vrste gob se nahajajo, in
shranimo podatke. Aplikacija ob shranjevanju samodejno pridobi podatke o trenutni
lokaciji in o trenutnih vremenskih razmerah. Podatke o vremenu pridobimo s pomočjo
OpenWeatherMap API-ja.
40
Spodnji funkciji prikazujeta programsko kodo, ki se izvede ob dodajanju nove lokacije gob
oz. ob spreminjaju obstoječe lokacije. Preverimo, ali smo poimenovali lokacijo in izbrali
vrsto gobe. Nato pregledamo, katere vrste gob smo označili, naložimo sliko na strežnik in
shranimo podatke o lokaciji tako na telefon kot na strežnik.
• Shranjevanje lokacije gob v programskem jeziku Java: public void onSave(View v){
if(!edName.getText().toString().equals("Poimenuj ") &&
stIzbranihGob(gobe)!=0){
if(stateNew) {
app.all = app.getAll();
}
for (TagTextView tv:gobe) {
tv.updateObjectState(); //sets LocationTag
if (stateNew) {
app.getAll2().addNewLocationGoba(tv.getTag());
}
}
if (stateNew) {
app.getAll2().addLocation(l);
uploadimage();
}
save();
finish();
}else{
Toast.makeText(ActivityLocation.this, "Nisi vpisal imena oz.
izbral gob!", Toast.LENGTH_SHORT).show();
}
}
• Shranjevanje lokacije gob v programskem jetziku Kotlin: fun onSave(v: View) {
if (edName?.text.toString() != "Poimenuj " && stIzbranihGob(gobe!!)
!= 0) {
if (stateNew) {
app?.all = app?.getAll()
}
for (tv in gobe!!) {
tv.updateObjectState() //sets LogationTag
if (stateNew) {
app?.getAll2()?.addNewLocationGoba(tv.tag)
}
}
if (stateNew) {
app?.getAll2()?.addLocation(l!!)
uploadimage()
}
save()
finish()
} else {
Toast.makeText(this@KotlinActivityLocation, "Nisi vpisal imena
oz. izbral gob!", Toast.LENGTH_SHORT).show()
}
}
41
7.9 Shranjevanje in pridobivanje podatkov
Na samem začetku smo podatke o lokacijah gob shranjevali samo na uporabnikovih
mobilnih naprav v obliki datoteke JSON. V datoteki JSON so bili shranjeni podatki o
uporabniku in vse njegove dodane lokacije gob. Lokacije gob vsebujejo podatke, kdaj je
uporabnik dodal lokacijo, podatke o vrstah gob, ki se nahajajo na lokaciji, pot do
fotografije gobe, podatke o lokaciji in vremenu. Za serializacijo objektov smo uporabili
knjižnico Gson [16].
• Shranjevanje podatkov v datoteko JSON v programskem jeziku Java public static boolean save(DataAll a, File file) {
if (isExternalStorageWritable()) {
try {
long start = System.currentTimeMillis();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
PrintWriter pw = new PrintWriter(file);
String sss=gson.toJson(a);
pw.println(sss);
pw.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("Error save! (FileNotFoundException)");
} catch (IOException e) {
System.out.println("Error save! (IOException)");
}
} else{
System.out.println(file.getAbsolutePath()+" NOT Writable");
}
return false;
}
• Shranjevanje podatkov v datoteko JSON v programskem jeziku Kotlin fun save(a: KotlinDataAll, file: File): Boolean {
if (isExternalStorageWritable()) {
try {
val start = System.currentTimeMillis()
val gson = GsonBuilder().setPrettyPrinting().create()
val pw = PrintWriter(file)
val sss = gson.toJson(a)
pw.println(sss)
pw.close()
return true
} catch (e: FileNotFoundException) {
e.printStackTrace()
println("Error save! (FileNotFoundException)")
} catch (e: IOException) {
println("Error save! (IOException)")
}
} else {
println(file.absolutePath + " NOT Writable")
}
42
return false
}
Za shranjevanje in pridobivanje podatkov iz datoteke JSON imamo narejen razred DataAll,
kjer imamo definirane potrebne spremenljivke. Poglejmo si del razreda brez metod:
• DataAll v programskem jeziku Java public class DataAll {
public static final String LOKACIJA_ID = "lokacija_id";
public static SimpleDateFormat dt = new
SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
private User userMe;
private GobaList gobaList;
private ArrayList<Lokacija> lokacijaList;
private ArrayList<LokacijaGoba> lokacijaGobaList;
...
}
• DataAll v programskem jeziku Kotlin open class KotlinDataAll {
val LOKACIJA_ID = "lokacija_id"
var dt = SimpleDateFormat("dd.MM.yyyy HH:mm:ss")
private var userMe: KotlinUser? = null
private var gobaList: KotlinGobaList?=null
private var lokacijaList: ArrayList<KotlinLokacija>? = null
private var lokacijaGobaList: ArrayList<KotlinLokacijaGoba>?=null
...
}
Ker smo želeli zavarovati uporabnikove podatke, ki so se prej shranjevali samo na
uporabnikovi napravi, smo se odločili, da shranjujemo podatke tudi v podatkovni bazi. Na
spletni strani 000webhost [17] smo si ustvarili račun in svojo domeno. Nato smo naredili
preprosto podatkovno bazo (Slika 7.4), kjer si shranjujemo podatke o uporabnikih,
podatke o ocenah slik in podatke o slikah gob uporabnikov.
43
Slika 7.4: Podatkovni model
Podatke o lokacijah gob od uporabnikov shranjujemo na strežniku v obliki datoteke JSON.
Pošiljanje in pridobivanje vseh podatkov na strežnik smo naredili s pomočjo PHP skript.
Podatke s strežnika pridobimo tako, da podamo URL, kjer se datoteka od uporabnika na
strežniku nahaja, in uporabimo vgrajeno knjižnico HttpURLConnection. S pomočjo knjižice
odpremo povezavo in začnemo prepisovati podatke iz strežnika v datoteko na mobilno
napravo. Ko prepišemo celotno datoteko se povezava zapre.
• Prenos datoteke JSON s strežnika in shranjevanje le-te na mobilno napravo v
programskem jeziku Java void downloadFile(String dwnload_file_path){
try {
URL url = new URL(dwnload_file_path);
HttpURLConnection urlConnection = (HttpURLConnection)
url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File file = new File(this.getExternalFilesDir(DATA_MAP),
""+ FILE_NAME);
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
totalSize = urlConnection.getContentLength();
byte[] buffer = new byte[1024];
int bufferLength = 0;
44
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
}
fileOutput.close();
} catch (final MalformedURLException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
catch (final Exception e) {
}
}
• Prenos datoteke JSON s strežnika in shranjevanje le-te na mobilno napravo v
programskem jeziku Kotlin
internal fun downloadFile(dwnload_file_path: String) {
try {
var downloadedSize = 0
val url = URL(dwnload_file_path)
val urlConnection = url.openConnection() as HttpURLConnection
urlConnection.requestMethod = "GET"
urlConnection.doOutput = true
urlConnection.connect()
val file = File(this.getExternalFilesDir(DATA_MAP), "" +
FILE_NAME)
val fileOutput = FileOutputStream(file)
val inputStream = urlConnection.inputStream
totalSize = urlConnection.contentLength
val buffer = ByteArray(1024)
var bufferLength = 0
do {
bufferLength = inputStream.read(buffer)
fileOutput.write(buffer, 0, bufferLength)
downloadedSize += bufferLength
} while (bufferLength > 0)
fileOutput.close()
} catch (e: MalformedURLException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: Exception)
}
}
45
7.10 Prikaz lokacij gob
Vse lokacije gob, ki jih je dodal uporabnik, prikazujemo v seznamu (Slika 7.6Slika 7.6).
Poznamo več vrst seznamov, ki jih uporabljamo za prikaz podatkov. Odločili smo se, da
ustvarimo seznam s pomočjo grafične komponente RecyclerView. RecyclerView je bolj
napredna in prilagodljiva verzija ListView, ki pripomore k hitrejšemu premikanju po
seznamu ob večji količini podatkov. Za uporabo smo morali v Gradle vključiti RecyclerView
knjižnico. Nato smo v datoteki XML naredili izgled ene vrstice (Slika 7.5), ki smo jo v
programski kodi uporabili za ustvarjanje vseh vrstic v seznamu.
Slika 7.5: Izgled vrstice seznama
Da smo lahko vnesli vse svoje podatke v seznam, smo morali narediti razred, ki je dedoval
od razreda RecyclerView.Adapter. Ta razred ustvari vrstice in jih napolni s potrebnimi
podatki. Znotraj razreda je še ena prednost RecyclerView, in sicer ko vrstice več ne
potrebujemo oz. ni več vidna, jo ponovno uporabimo in napolnimo z novimi podatki s
pomočjo implementirane metode onBindViewHolder. To pomeni, da uporabljamo
minimalno število vrstic za prikaz podatkov ter s tem pohitimo premikanje po seznamu.
• Usvarjanje nove vrstice v seznamu v programskem jeziku Java @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v =
LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout,
parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
• Usvarjanje nove vrstice v seznamu v programskem jeziku Kotlin override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
ViewHolder? {
val v =
LayoutInflater.from(parent.context).inflate(R.layout.rowlayout, parent,
false)
return ViewHolder(v)
}
46
Slika 7.6: Seznam lokacij gob v mobilni aplikaciji JazGobar
7.11 Prikaz podrobosti o lokaciji gobe v novem oknu
Ob pritisku na posamezni vnos v seznamu se mora odpreti novo okno, kjer se prikažejo
podrobnosti o lokaciji (Slika 7.7). To smo naredili tako, da smo implementirali metodo
OnClickListener na vsako vrstico in v novo okno prenesli ID lokacije ter prikazali vse
podatke.
Slika 7.7: Prikaz podrobnosti o lokaciji gob v mobilni aplikaciji JazGobar
47
7.12 Končni izdelek
Med aplikacijo, ki je izdelana s programskim jezikom Java, in tisto, ki je izdelana s
programskim jezikom Kotlin, ni popolnoma nobene vizualne ali funkcionalne razlike.
Za konec smo naredili še nekaj manjših primerjav (testov) med obema aplikacijama.
Primerjave so bile izvedene na Android emulatorju z naslednjimi specifikacijami:
• velikost zaslona: 5,5 palcev,
• ločljivost zaslona: 1280 x 720 px,
• pomnilnik (RAM): 2048 MB,
• spomin: 800 MB.
Primerjave (Tabela 1) smo izvajali na operacijskem sistem Android verzija 5.0 (Lolipop). V
vseh primerjavah je boljša aplikacija, ki je napisana v programskem jeziku Java. Razlika v
odstotkih med obema aplikacijama ni tako zelo velika, razen pri zasedenosti prostora na
mobilni napravi. Pri tako majhni mobilni aplikaciji kot je naša, to ni tako zelo velika razlika,
ampak če vzamemo za primerjavo aplikacije, ki so velike nekaj sto MB, je razlika veliko
večja. Ampak v današnjih časih, ko imamo nekaj deset GB spomina, nas tistih nekaj
odstokov razlike v zasedenosti prostora ne skrbi.
Tabela 1: Primerjava velikosti in porabe pomnilnika med obema aplikacijama
Aplikacija izdelana v Javi
Aplikacija izdelana v Kotlinu
Razlika v odstotkih
Velikost APK-ja 5,9 MB 6,2 MB 5 %
Zaseden prostora v mobilni napravi
20,6 MB 24,7 MB 20 %
Najmanjša poraba pomnilnika
23 MB 25 MB 9 %
Največja poraba pomnilnika
49,5 MB 52 MB 5 %
48
8 SKLEP
Zadnjih nekaj let najdemo veliko različnih mobilnih aplikacij za Android operacijski sistem.
Večina teh aplikacij je razvitih s pomočjo programskega jezika Java. Tako kot povsod
drugje tudi pri programskih jezikih gre razvoj naprej. Tako so razvili programski jezik Kotlin
ter ga dodali v Android Studio kot izbiro poleg Jave.
S pomočjo izdelane mobilne aplikacije JazGobar smo se spoznali s programskim jezikom
Kotlin, njegovimi prednostmi in slabostmi. S programskim jezikom Kotlin v večini
primerov, še posebaj pri razredih, napišemo veliko manj kode kot v programskem jeziku
Java. Manj kode pomeni manj napak med samim pisanjem. Velika prednost programskega
jezika Kotlin v primerjavi z Javo je delo z ničelnimi spremenljivkami. Tudi programski jezik
Java ima svoje prednosti, to je, da nam ustvari manjšo aplikacijo in hitreje izvede prvo
prevajanje aplikacije z Gradl-om.
Končnega odgovora na vprašanje, kateri programski jezik je bolje izbrati, nimamo, saj je
odvisno od razvijalca in njegovih izkušenj. Če smo začetniki in nismo nikoli razvijali
mobilnih aplikacij za Android operacijski sistem, je bolje, da začnemo razvijati s
programskim jezikom Java, ker imamo veliko več literature, primerov, navodil, različnih
rešitev za probleme, na katere bomo naleteli med razvojem. Menimo, da nekdo, ki se
nauči oziroma že zna napisati dobro kodo v programskem jeziku Java, bo znal v Kotlinu
napisati boljšo programsko kodo, kar obratno niti ne velja. Vsekakor pa ne bo nič narobe,
če kar neposredno začnemo s programskim jezikom Kotlin, ki je zelo enostaven za učenje.
Pojavili se bodo minusi pri iskanju rešitev za naše probleme, saj je razvijalska skupnost še
v razvoju. Za izkušene razvijalce je priporočljivo preizkusiti programski jezik Kotlin, saj
odpravlja večino težav in pomankljivosti programskega jezika Java.
Edina pomankljivost, na katero smo naleteli med razvojem s programskim jezikom Kotlin,
je vgrajen pretvorvnik iz Jave v Kotlin. Da ne boste razumeli napačno, pretvornik deluje
več kot odlično, le nekaj manjših napak naredi, ki pa jih v večini primerov odpravimo v
49
zelo kratkem času. Slabost je samo ta, da neposredno pretvarja iz Jave v Kotlin, ne da bi
upošteval vse prednosti programskega jezika Kotlin. Tukaj mislimo predvsem na
upravljanje z ničelnimi spremenljivkami, urejanje SharedPreferences itd.
Slika 8.1: Primerjava programskih jezikov Java in Kotlin (Vir: https://www.xenonstack.com/blog/updates/overview-of-kotlin-comparison-
between-kotlin-java)
Menimo, da se bo programski jezik Kotlin v bližnji prihodnosti razvil do te mere, da bo v
popolnosti zasenčil Javo. Že kar nekaj znanih podjetij je svoje mobilne aplikacije pretvorilo
v Kotlin programski jezik, nekatera med njimi so: Pinterest, Trello, Evernote, Coursera itd.
50
LITERATURA IN VIRI
[1] Wikipedia, „Android Studio,“ [Elektronski]. Dostopno na:
https://en.wikipedia.org/wiki/Android_Studio. [24. 03. 2018].
[2] „Android Developers,“ [Elektronski]. Dostopno na:
http://androiddoc.qiniudn.com/tools/studio/index.html. [24. 03. 2018].
[3] Wikipedia, „Android (operating system),“ [Elektronski]. Dostopno na:
https://en.wikipedia.org/wiki/Android_(operating_system). [25. 03. 2018].
[4] Mernik M., Žumer V. Programski jeziki. Maribor: Fakulteta za elektrotehniko,
računalništvo in informatiko, Inštitut za računalništvo, 2003.
[5] Wikipedia, „Java (programming language),“ [Elektronski]. Dostopno na:
https://en.wikipedia.org/wiki/Java_(programming_language). [28. 03. 2018].
[6] Wikipedia, „Kotlin (programming language),“ [Elektronski]. Dostopno na:
https://en.wikipedia.org/wiki/Kotlin_(programming_language). [28. 03. 2018].
[7] Leiva A. Kotlin for Android Developers: Learn Kotlin the easy way while developing an
Android App. Lean Publishing, 2017.
[8] Yalantis, „Kotlin vs Java: Basic Syntax Differences,“ [Elektronski]. Dostopno na:
https://yalantis.com/blog/kotlin-vs-java-syntax/. [31. 03. 2018].
[9] Kotlinlang, „Reference,“ [Elektronski]. Dostopno na:
https://kotlinlang.org/docs/reference/. [01. 04. 2018].
[10] Tutorialspoint, „Java Tutorial,“ [Elektronski]. Dostopno na:
https://www.tutorialspoint.com/java/index.htm. [01. 04. 2018].
[11] Applikeysolutions, „Kotlin vs Java: What is Better for Android Development?,“
[Elektronski]. Dostopno na: https://applikeysolutions.com/blog/kotlin-vs-java-what-
is-better-for-android-development. [04. 04. 2018].
[12] T. Software, „Java vs Kotlin: Which Programming Language Is Better For Android
Developers?,“ [Elektronski]. Dostopno na: http://teks.co.in/site/blog/java-vs-kotlin-
which-programming-language-is-better-for-android-developers/. [06. 04. 2018].
51
[13] AndroidAuthority, „Kotlin vs Java: key differences between Android’s officially-
supported languages,“ [Elektronski]. Dostopno na:
https://www.androidauthority.com/kotlin-vs-java-783187/. [06. 04. 2018].
[14] ArtTouch, „Kotlin vs. Java: First Impressions Using Kotlin for a Commercial Android
Project,“ [Elektronski]. Dostopno na: https://arctouch.com/blog/kotlin-vs-java/. [06.
04. 2018].
[15] Envatotuts+, „Java vs. Kotlin: Should You Be Using Kotlin for Android Development?,“
[Elektronski]. Dostopno na: https://code.tutsplus.com/articles/java-vs-kotlin-should-
you-be-using-kotlin-for-android-development--cms-27846. [06. 04. 2018].
[16] GitHub, "Gson library," [Elektronski]. Dostopno na: https://github.com/google/gson.
[22. 05. 2018].
[17] 000webhost, "Free web hosting," [Elektronski]. Dostopno na:
https://www.000webhost.com/. [22. 05. 2018].
IZJAVA O AVTORSTVU IN ISTOVETNOSTI TISKANE IN ELEKTRONSKE OBLIKE ZAKLJUČNEGA DELA
Ime in priimek študent‐a/‐ke: Nikolaj Čolić
Študijski program: Računalništvo in informacijske tehnologije
Naslov zaključnega dela: Primerjava programskih jezikov Java in Kotlin na primeru
implementacije aplikacije JazGobar
Mentor: doc. dr. Matej Črepinšek
Somentor:
Podpisan‐i/‐a študent/‐ka Nikolaj Čolić
• izjavljam, da je zaključno delo rezultat mojega samostojnega dela, ki sem ga izdelal/‐a ob pomoči mentor‐ja/‐ice oz. somentor‐ja/‐ice;
• izjavljam, da sem pridobil/‐a vsa potrebna soglasja za uporabo podatkov in avtorskih del v zaključnem delu in jih v zaključnem delu jasno in ustrezno označil/‐a;
• na Univerzo v Mariboru neodplačno, neizključno, prostorsko in časovno neomejeno prenašam pravico shranitve avtorskega dela v elektronski obliki, pravico reproduciranja ter pravico ponuditi zaključno delo javnosti na svetovnem spletu preko DKUM; sem seznanjen/‐a, da bodo dela deponirana/objavljena v DKUM dostopna široki javnosti pod pogoji licence Creative Commons BY‐NC‐ND, kar vključuje tudi avtomatizirano indeksiranje preko spleta in obdelavo besedil za potrebe tekstovnega in podatkovnega rudarjenja in ekstrakcije znanja iz vsebin; uporabnikom se dovoli reproduciranje brez predelave avtorskega dela, distribuiranje, dajanje v najem in priobčitev javnosti samega izvirnega avtorskega dela, in sicer pod pogojem, da navedejo avtorja in da ne gre za komercialno uporabo;
• dovoljujem objavo svojih osebnih podatkov, ki so navedeni v zaključnem delu in tej izjavi, skupaj z objavo zaključnega dela;
• izjavljam, da je tiskana oblika zaključnega dela istovetna elektronski obliki zaključnega dela, ki sem jo oddal/‐a za objavo v DKUM.
Uveljavljam permisivnejšo obliko licence Creative Commons: CC BY 4.0 (navedite obliko)
Začasna nedostopnost:
Zaključno delo zaradi zagotavljanja konkurenčne prednosti, zaščite poslovnih skrivnosti, varnosti ljudi in narave, varstva industrijske lastnine ali tajnosti podatkov naročnika: (naziv in naslov naročnika/institucije) ne sme biti javno dostopno do (datum odloga javne objave ne sme biti daljši kot 3 leta od zagovora dela). To se nanaša na tiskano in elektronsko obliko zaključnega dela.
Temporary unavailability:
To ensure competition priority, protection of trade secrets, safety of people and nature, protection of industrial property or secrecy of customer's information, the thesis _________________________ (institution/company name and address) must not be accessible to the public till (delay date of thesis availability to the public must not exceed the period of 3 years after thesis defense). This applies to printed and electronic thesis forms.
Datum in kraj: Podpis študent‐a/‐ke:
Podpis mentor‐ja/‐ice:
(samo v primeru, če delo ne me biti javno dostopno)
Ime in priimek ter podpis odgovorne osebe naročnika in žig:
(samo v primeru, če delo ne sme biti javno dostopno)