Kotlin is een moderne programmeertaal die compileert met Java bytecode. Het is gratis en open source en belooft om het coderen voor Android nog leuker te maken.
In het vorige artikel in deze serie, hoorde je over nullability, loops en omstandigheden in Kotlin. In deze zelfstudie blijven we de taal leren door naar de bereik- en verzamelingen-API in Kotlin te kijken.
Een bereik in Kotlin is een uniek type dat een startwaarde en een eindwaarde definieert. Met andere woorden, het is een interval tussen een begin- en een eindwaarde. Ranges in Kotlin zijn gesloten, wat betekent dat de startwaarde en eindwaarde in het bereik zijn inbegrepen.
We zullen nu kijken naar de verschillende manieren om ranges te maken in Kotlin.
...
operatorval oneToFive = 1 ... 5
In de bovenstaande code hebben we een gesloten bereik gemaakt. Deze variabele oneToFive
bevat de volgende waarden: 1, 2, 3, 4, 5. We kunnen eroverheen lopen met behulp van de voor
loop-constructie.
for (n in oneToFive) print (n)
De bovenstaande code kan worden ingekort tot:
voor (n in 1 ... 5) print (n)
We kunnen ook een reeks tekens maken:
val aToZ = "a" ... "z"
De variabele A tot Z
zal alle letters in het Engelse alfabet hebben.
rangeTo ()
FunctieDe ...
operator kan worden vervangen door de rangeTo ()
uitbreidingsfunctie om een bereik te maken. We kunnen dit bijvoorbeeld ook doen 1.rangeTo (5)
en het zou nog steeds dezelfde resultaten hebben als het gebruik van de ...
operator zoals eerder besproken.
val oneToFive: IntRange = 1.rangeTo (5)
downto ()
FunctieDit is een andere uitbreidingsfunctie waarmee een bereik wordt gemaakt, beginnend bij een bepaald getal tot een ander getal.
val fiveToOne = 5.downTo (1)
We kunnen het bereik aanpassen met behulp van de stap()
functie. Hiermee wordt de delta tussen elk element in het bereik gewijzigd.
val oneToTenStep = 1 ... 10 stap 2 // 1, 3, 5, 7, 9
De bovenstaande code bevat oneven nummers tussen 1 en 10.
in
operatorDe in
operator wordt gebruikt om vast te stellen of een waarde in een bepaald bereik aanwezig is.
if (5 in 1 ... 10) print ("Yes 5 is in the range") // prints "Yes 5 is in the range"
In de bovenstaande code hebben we gecontroleerd of 5 binnen het bereik 1 ... 10 is met de in
operator. We kunnen ook het tegenovergestelde doen door te gebruiken !n
om te controleren of 5 niet binnen het bereik valt.
Collecties worden gebruikt om groepen gerelateerde objecten in het geheugen op te slaan. In een verzameling kunnen we de objecten ophalen, opslaan of ordenen. Kotlin biedt zijn collecties-API als een standaardbibliotheek die is gebouwd bovenop de Java Collections API. (We bespreken interfaces in Kotlin in een volgend bericht.)
Merk op dat deze interfaces tijdens de compilatie aan hun implementatie zijn gekoppeld. U kunt de implementatiebroncode niet zien in Kotlin, omdat de collecties daadwerkelijk worden geïmplementeerd door de standaard Java-verzamelingen zoals ArrayList
, Kaarten
, Hash kaart
, sets
, HashSet
, Lijst
enzovoorts. Als u de API voor collecties in Kotlin echt wilt begrijpen, moet u bekend zijn met deze basisklassen en interfaces in Java.
In dit gedeelte leren we over de Lijst
, set
en Kaart
collecties in Kotlin. (Als je een opfriscursus op arrays in Kotlin wilt, bezoek dan de eerste tutorial in deze serie.)
De collecties van Kotlin geven ons de mogelijkheid om veel te bereiken met slechts een kleine code-in tegenstelling tot Java, dat veel code lijkt te hebben om een beetje te bereiken! Kotlin heeft twee varianten van collecties: veranderbaar en onveranderlijk. Een veranderlijke verzameling biedt ons de mogelijkheid om een verzameling aan te passen door een element toe te voegen, te verwijderen of te vervangen. Onveranderlijke collecties kunnen niet worden gewijzigd en hebben deze hulpmethoden niet.
Merk op dat de toevoeging, verwijdering of vervanging van een element in een onveranderlijke verzameling mogelijk is via operatorfuncties (we komen daar binnenkort op), maar deze zullen uiteindelijk een nieuwe verzameling creëren.
Iterable
InterfaceDe Kotlin Iterable
interface staat bovenaan de klassenhiërarchie van de verzameling. Met deze interface kunnen collecties worden weergegeven als een reeks elementen (die natuurlijk kunnen worden herhaald).
openbare interface Iterablepublic abstract operator fun iterator (): Iterator
Verzameling
InterfaceDe Kotlin Verzameling
interface verlengt de Iterable
interface. De Verzameling
interface is onveranderlijk. Met andere woorden, u hebt alleen-lezen toegang tot collecties. De set
en Lijst
interfaces (hierover binnenkort meer) in Kotlin breiden deze interface uit.
Enkele van de functies en eigenschappen die beschikbaar zijn in de Verzameling
interface zijn:
grootte
: deze eigenschap retourneert de grootte van de verzameling.is leeg()
: geeft waar als de verzameling leeg of anderszins niet waar is. bevat (element: E)
: retourneert true als het element dat in het argument is opgegeven aanwezig is in de verzameling.containsAll (element: Verzameling)
: geeft true terug als het element in de verzameling dat is doorgegeven als argument aanwezig is in de verzameling. openbare interface Collection: Iterable public val size: Int public fun is Empty (): Boolean public operator fun contains (element: @UnsafeVariance E): Boolean override fun iterator (): Iterator public fun containsAll (elements: Collection<@UnsafeVariance E>): Boolean
MutableIterable
InterfaceDeze interface in Kotlin geeft ons een gespecialiseerde veranderlijke iterator van de ouder Iterable
interface.
openbare interface MutableIterable: Iterable overschrijven leuke iterator (): MutableIterator
MutableCollection
InterfaceDe MutableCollection
interface in Kotlin is een gespecialiseerde interface waarmee collecties kunnen worden gewijzigd. Met andere woorden, bewerkingen voor toevoegen en verwijderen kunnen voor een bepaalde verzameling worden uitgevoerd. Deze interface breidt beide uit Verzameling
interface en de MutableIterable
interface die hierboven al is besproken. De MutableSet
en MutableList
interfaces (we komen ze binnenkort te weten) in Kotlin breiden deze interface uit. De functies die beschikbaar zijn in deze interface-afgezien van degene die beschikbaar zijn bij zijn ouders-zijn:
toevoegen (element: E)
: voegt het element door dat als een argument is doorgegeven aan de verzameling en geeft true als geslaagd of false als de verzameling geen duplicaten ondersteunt en het element al aanwezig is.verwijderen (element: E)
: verwijdert het element dat als een argument uit de verzameling is doorgegeven. Geeft true terug als succesvol of onwaar als deze niet aanwezig was in de verzameling.addAll (elements: Collection)
: voegt alle elementen in de verzameling toe die als argumenten zijn doorgegeven aan de verzameling. Geeft true als succesvol of false als niets is toegevoegd.removeAll (elements: Collection)
: verwijdert alle elementen in de verzameling die als argumenten zijn doorgegeven. Geeft true als succesvol of false als niets is verwijderd.retainAll (elements: Collection)
: behoudt alleen de elementen in de verzamelingen die zijn doorgegeven als argumenten. Geeft true als succesvol of false als niets werd behouden. duidelijk()
: verwijdert alle elementen uit deze verzameling.openbare interface MutableCollection: Verzameling , MutableIterable overschrijven leuke iterator (): MutableIterator public fun add (element: E): Boolean public fun remove (element: E): Boolean public fun addAll (elements: Collection ): Boolean public fun removeAll (elements: Collection ): Boolean public fun retainAll (elementen: Verzameling ): Boolean public fun clear (): eenheid
Nu heb je geleerd over de top-interfaces in de collectie-klassenhiërarchie in Kotlin, laten we nu kijken hoe Kotlin collecties zoals Lijsten, Sets en Kaarten verwerkt in het resterende deel van de tutorial.
Een lijst is een geordende verzameling elementen. Dit is een populaire verzameling die veel wordt gebruikt. Laten we kijken naar verschillende manieren om een lijst in Kotlin te maken.
lijst van()
FunctieIn Kotlin kunnen we een onveranderlijke (alleen-lezen) lijst maken met behulp van de lijst van()
hulpfunctie van de standaardbibliotheek van Kotlin. Deze functie retourneert een Kotlin Lijst
interfacetype.
var nummers: lijst= listOf (1, 2, 3, 4, 5) var names: lijst = listOf ("Chike", "Nnamdi", "Mgbemena") voor (naam in namen) println (name)
Als u de bovenstaande code uitvoert, wordt afgedrukt:
Chike Nnamdi Mgbemena
Bovendien kunnen we waarden van verschillende typen in de lijst van()
als argumenten en het resultaat zal nog steeds werken - het zal een lijst van gemengd type zijn.
var listMixedTypes = listOf ("Chike", 1, 2.445, 's') // zal nog steeds compileren
emptyList ()
FunctieDeze functie maakt gewoon een lege onveranderlijke lijst en retourneert een Kotlin Lijst
interfacetype.
val emptyList: lijst= emptyList ()
listOfNotNull ()
FunctieDeze functie maakt een nieuwe onveranderlijke lijst met alleen elementen die niet nul zijn. Merk op dat deze functie een Kotlin retourneert Lijst
interfacetype ook.
val nonNullsList: lijst= listOfNotNull (2, 45, 2, null, 5, null)
De Lijst
interface van de standaardbibliotheek van Kotlin breidt alleen de Verzameling
interface. Met andere woorden, de enige ouder is de Verzameling
interface. Het overschrijft alle functies in de bovenliggende interface om tegemoet te komen aan zijn speciale behoeften en definieert ook zijn eigen functies, zoals:
get (index: Int)
: een functie-operator die het element retourneert naar de opgegeven index. indexOf (element: E)
: retourneert de index van de eerste instantie van het element dat is doorgegeven als een argument in de lijst, of -1 als er geen is gevonden.lastIndexOf (element: E)
: retourneert de index van de laatste keer dat het element is doorgegeven als een argument in de lijst, of -1 als er geen is gevonden. listIterator ()
: geeft een lijst-iterator over de elementen in de lijst.subList (fromIndex: Int, toIndex: Int)
: retourneert een lijst met het gedeelte van de lijst tussen de opgegeven begin- en eindindexen. println (names.size) // 3 println (names.get (0)) // "Chike" println (names.indexOf ("Mgbemena")) // 2 println (names.contains ("Nnamdi")) // 'echte'
arrayListOf ()
FunctieDit maakt een veranderbare lijst en retourneert een Java ArrayList
type.
val stringList: ArrayList= arrayListOf ("Hallo Jij daar")
mutableListOf ()
FunctieOm waarden in een lijst toe te voegen, te verwijderen of te vervangen, moeten we de lijst veranderbaar maken. We kunnen een onveranderlijke lijst omzetten naar een veranderlijke lijst door de functie aan te roepen toMutableList ()
op de lijst. Merk echter op dat deze methode een nieuwe lijst zal maken.
var mutableNames1 = names.toMutableList () mutableNames1.add ("Ruth") // nu wijzigbaar en "Ruth" toegevoegd aan lijst
Om vanuit het niets een veranderlijke lijst van een bepaald type te maken, bijv. Draad
, we gebruiken mutableListOf
, terwijl voor gemengde typen we gewoon de mutableListOf ()
functie in plaats daarvan.
// een veranderbare lijst van een bepaald type, b.v. String val mutableListNames: MutableList= mutableListOf ("Josh", "Kene", "Sanya") mutableListNames.add ("Mary") mutableListNames.removeAt (1) mutableListNames [0] = "Oluchi" // vervangt het element in index 0 door "Oluchi" // a veranderbare lijst van gemengde typen val mutableListMixed = mutableListOf ("BMW", "Toyota", 1, 6.76, 'v')
Elk van deze functies retourneert a MutableList
Kotlin-interfacetype. Deze interface breidt beide uit MutableCollection
en Lijst
interfaces die eerder in deze sectie zijn besproken. De MutableList
interface voegt methoden toe voor het ophalen of vervangen van een artikel op basis van zijn positie:
set (index: Int, element: E)
: vervangt een element in de lijst door een ander element. Dit retourneert het element eerder op de opgegeven positie.toevoegen (index: Int, element: E)
: voegt een element in bij de opgegeven index. removeAt (index: Int)
: verwijdert het element van een bepaalde index. val mutableListFood: MutableList= mutableListOf ("Rice & stew", "Jollof rice", "Eba & Egusi", "Fried rice") mutableListFood.remove ("Fried rice") mutableListFood.removeAt (0) mutableListFood.set (0, "Beans") mutableListFood. add (1, "Bread & tea") for (foodName in mutableListFood) println (foodName)
Als u de bovenstaande code uitvoert, produceren we het volgende resultaat:
Bonen Brood en thee Eba & Egusi
Merk op dat al deze functies een Java maken ArrayList
Achter de schermen.
Een set is een ongeordende verzameling unieke elementen. Met andere woorden, het kan geen duplicaten hebben! Laten we eens kijken naar enkele van de verschillende manieren om een set te maken in Kotlin. Elk van deze creëert een andere datastructuur, die elk is geoptimaliseerd voor een bepaald soort taak.
Setof ()
FunctieOm een onveranderlijke (alleen-lezen) set in Kotlin te creëren, kunnen we de functie gebruiken Setof ()
, die een Kotlin retourneert set
interfacetype.
// maakt een onveranderlijke set gemengde typen val mixedTypesSet = setOf (2, 4.454, "how", "far", 'c') // compileert var intSet: Set= setOf (1, 3, 4) // alleen gehele getallen toegestaan
Merk op dat de Kotlin set
interface breidt alleen de Kotlin uit Verzameling
interface en vervangt alle eigenschappen die beschikbaar zijn in de bovenliggende.
hashSetOf ()
Functie De ... gebruiken hashSetOf ()
functie maakt een Java HashSet
verzameling waarin elementen in een hash-tabel worden opgeslagen. Omdat deze functie een Java retourneert HashSet
type kunnen we elementen in de set toevoegen, verwijderen of wissen. Met andere woorden, het is veranderlijk.
val intsHashSet: java.util.HashSet= hashSetOf (1, 2, 6, 3) intsHashSet.add (5) intsHashSet.remove (1)
sortedSetOf ()
FunctieDe ... gebruiken sortedSetOf ()
functie maakt een Java TreeSet
verzameling achter de schermen, die elementen bestelt op basis van hun natuurlijke ordening of door een comparator. Deze set kan ook worden gewijzigd.
val intSSortedSet: java.util.TreeSet= sortedSetOf (4, 1, 7, 2) intsSortedSet.add (6) intsSortedSet.remove (1) intsSortedSet.clear ()
linkedSetOf ()
FunctieDeze functie retourneert een Java LinkedHashSet
type. Deze veranderlijke set onderhoudt een gekoppelde lijst van de vermeldingen in de set, in de volgorde waarin ze zijn ingevoegd.
val intsLinkedHashSet: java.util.LinkedHashSet= linkedSetOf (5, 2, 7, 2, 5) // 5, 2, 7 intsLinkedHashSet.add (4) intsLinkedHashSet.remove (2) intsLinkedHashSet.clear ()
mutableSetOf ()
FunctieWe kunnen gebruiken mutableSetOf ()
om een veranderlijke set te maken. Deze functie retourneert een Kotlin MutableSet
interfacetype. Achter de schermen creëert deze functie eenvoudig een Java LinkedHashSet
.
// maakt een veranderbare set van int-typen alleen val intsMutableSet: MutableSet= mutableSetOf (3, 5, 6, 2, 0) intsMutableSet.add (8) intsMutableSet.remove (3)
De MutableSet
interface breidt zowel de MutableCollection
en de set
interfaces.
Kaarten associëren sleutels met waarden. De sleutels moeten uniek zijn, maar de bijbehorende waarden hoeven dat niet te zijn. Op die manier kan elke sleutel worden gebruikt om de bijbehorende waarde op unieke wijze te identificeren, omdat de kaart ervoor zorgt dat u geen dubbele sleutels in de verzameling kunt hebben. Achter de schermen gebruikt Kotlin de Java Kaart
verzameling om het kaartverzamelingstype te implementeren.
kaart van()
FunctieOm een onveranderlijke of alleen-lezen te maken Kaart
collectie in Kotlin, gebruiken we de kaart van()
functie. We maken een kaart met deze functie door deze een lijst met paren te geven - de eerste waarde is de sleutel en de tweede de waarde. Als deze functie wordt aangeroepen, wordt een Kotlin geretourneerd Kaart
interfacetype.
val callingCodesMap: Map= mapOf (234 tot "Nigeria", 1 tot "USA", 233 tot "Ghana") voor ((sleutel, waarde) in callingCodesMap) println ("$ -code is de aanroepcode voor $ waarde") print (callingCodesMap [234]) // Nigeria
Als u de bovenstaande code uitvoert, wordt het resultaat weergegeven:
234 is de aanroepcode voor Nigeria 1 is de aanroepcode voor de VS 233 is de aanroepingscode voor Ghana
In tegenstelling tot de Lijst
en set
interfaces in Kotlin die de Verzameling
-interface, de Kaart
interface breidt helemaal niet uit. Sommige van de eigenschappen en functies die beschikbaar zijn in deze interface zijn:
grootte
: deze eigenschap retourneert de grootte van de kaartverzameling.is leeg()
: geeft true als de kaart leeg of anderszins false is.containsKey (sleutel: K)
: geeft waar als de kaart de sleutel in het argument bevat. containsValue (waarde: V)
: geeft true als de kaart een of meer sleutels toewijst aan de waarde die als een argument is doorgegeven.krijgen (sleutel: K)
: retourneert de waarde die overeenkomt met de opgegeven sleutel of 'null' als er geen wordt gevonden. sleutels
: deze eigenschap retourneert een onveranderlijk set
van alle toetsen op de kaart.waarden
: retourneert een onveranderlijk Verzameling
van alle waarden op de kaart.mutableMapOf ()
FunctieDe mutableMapOf ()
functie maakt een veranderlijke kaart voor ons zodat we elementen op de kaart kunnen toevoegen en verwijderen. Dit levert een Kotlin op MutableMap
interfacetype.
val valuta's MutableMap: MutableMap= mutableMapOf ("Naira" naar "Nigeria", "Dollars" naar "USA", "Pounds" naar "UK") println ("Landen zijn $ currenciesMutableMap.values") // Landen zijn [Nigeria, VS, VK ] println ("Valuta's zijn $ valuta'sMutableMap.keys") // Valuta's zijn valuta's [Naira, Dollars, Pounds] MutableMap.put ("Cedi", "Ghana") valuta MutableMap.remove ("Dollars")
De MutableMap
interface breidt het niet uit MutableCollection
interface; het is alleen de ouder is de Kaart
interface. Het heeft voorrang boven de sleutels
, entries
en waarden
eigenschappen van de bovenliggende interface om ze opnieuw te definiëren. Hier zijn enkele van de extra functies die beschikbaar zijn in de MutableMap
interface:
put (sleutel: K, waarde: V)
: voegt de sleutel, waardepaar in de kaart in. Hiermee wordt de vorige waarde die aan de sleutel is gekoppeld of null geretourneerd als de sleutel niet eerder is gebruikt. verwijderen (sleutel: K)
: verwijdert de sleutel en de gekoppelde waarde van de kaart. zet alle
(van: kaart)
: werkt de kaart bij met alle gegevens van de gegeven kaart. Nieuwe sleutels worden toegevoegd en bestaande sleutels worden bijgewerkt met nieuwe waarden. duidelijk()
: verwijdert alle elementen van de kaart. We kunnen de waarde voor een sleutel verkrijgen met behulp van de krijgen()
functie. We kunnen ook vierkante haakjesnotatie gebruiken als een snelkoppeling voor krijgen()
.
print (valuta's MutableMap.get ("Nigeria")) // zal Naira print afdrukken (valuta MutableMap ["Nigeria"]) // zal Naira afdrukken
hashMapOf ()
FunctieAls u deze functie gebruikt, wordt een Java geretourneerd Hash kaart
type dat veranderbaar is. De Hash kaart
klasse gebruikt een hashtabel om de Java te implementeren Kaart
interface.
val personsHashMap: java.util.HashMap= hashMapOf (1 tot "Chike", 2 tot "John", 3 tot "Emeka") personsHashMap.put (4, "Chuka") personsHashMap.remove (2) afdrukken (personsHashMap [1]) // zal Chike afdrukken
LinkedHashMap ()
FunctieDeze functie retourneert een Java LinkedHashMap
type dat veranderbaar is. De LinkedHashMap
klasse breidt Java uit Hash kaart
en onderhoudt een gekoppelde lijst van de vermeldingen op de kaart in de volgorde waarin ze zijn ingevoegd.
val postalCodesHashMap: java.util.LinkedHashMap= linkedMapOf ("NG" naar "Nigeria", "AU" naar "Australië", "CA" naar "Canada") postalCodesHashMap.put ("NA", "Namibia") postalCodesHashMap.remove ("AU") postalCodesHashMap.get ("CA") // Canada
sortedMapOf ()
FunctieDeze functie retourneert een Java SortedMap
type dat veranderbaar is. De Java SortedMap
class ziet dat de items op de kaart in een oplopende volgorde worden bijgehouden.
val personsSortedMap: java.util.SortedMap= separatedMapOf (2 tot "Chike", 1 tot "John", 3 tot "Emeka") personsSortedMap.put (7, "Adam") personsSortedMap.remove (3)
Vergeet niet dat de implementatie van deze verzameling-interfaces in Kotlin plaatsvindt tijdens het compileren.
Kotlin biedt ons veel nuttige operator-functies, uitbreidingsfuncties die kunnen worden gebruikt in verzamelingen. Laten we een paar van de nuttigste bekijken.
laatste()
FunctieDeze operatorfunctie retourneert het laatste element in een verzameling, zoals een lijst of set. We kunnen ook een predikaat leveren om binnen een subset van elementen te zoeken.
val stringList: lijst= listOf ("in", "the", "club") print (stringList.last ()) // zal "club" afdrukken // gegeven een predikaatafdruk (stringList.last it.length == 3) / / zal "de" val intSet: Set afdrukken = setOf (3, 5, 6, 6, 6, 3) print (intSet.last ()) // zal 6 afdrukken
eerste()
FunctieDeze operatorfunctie retourneert het eerste element wanneer het wordt aangeroepen in een verzameling, zoals een lijst of set. Als een predikaat wordt gegeven, gebruikt het vervolgens het predikaat om de bewerking te beperken tot een subset elementen.
print (stringList.first ()) // print "in" print (intSet.first ()) // print 3
max ()
FunctieHet aanroepen van deze operatorfunctie op een verzameling zoals een lijst of set retourneert het grootste element, of null als er geen grootste element is gevonden.
val intList: lijst= listOf (1, 3, 4) print (intList.max ()) // print 4 print (intSet.max ()) // print 6
laten vallen()
FunctieAls deze operatorfunctie wordt aangeroepen, wordt een nieuwe lijst of reeks geretourneerd die alle elementen behalve de eerste n elementen bevat.
print (stringList.drop (2)) // zal "club" afdrukken
plus()
FunctieDeze operatorfunctie retourneert een verzameling die alle elementen van het origineel bevat en vervolgens het gegeven element als dit nog niet in de verzameling staat. Dit zal uiteindelijk een nieuwe lijst maken in plaats van de lijst te wijzigen.
print (intList.plus (6)) // zal [1, 3, 4, 6] afdrukken
min()
FunctieHet tegenovergestelde van de plus()
functie is de min()
functie. Het geeft een verzameling terug die alle elementen van de originele set bevat behalve het gegeven element. Dit leidt ook tot het maken van een nieuwe lijst in plaats van het wijzigen van de lijst.
print (intList.minus (3)) // zal printen [1, 4]
gemiddelde()
FunctieHet aanroepen van deze operatorfunctie retourneert een gemiddeld aantal elementen in de verzameling.
print (intList.average ()) // zal 2.6666666666666665 afdrukken
De meeste van deze uitbreidingsfuncties zijn beschikbaar in de standaardbibliotheek van Kotlin collections. U wordt geadviseerd om de documentatie te lezen om meer te weten te komen over de anderen.
In deze zelfstudie hebt u informatie ontvangen over de bereik- en verzamelingen-API in de Kotlin-programmeertaal. In de volgende tutorial in de Kotlin From Scratch-serie, maak je kennis met functies in Kotlin. Tot ziens!
Voor meer informatie over de Kotlin-taal, raad ik aan de Kotlin-documentatie te bezoeken. Of bekijk enkele van onze andere Android-apps voor app-ontwikkeling hier op Envato Tuts!