Wikisage, de vrije encyclopedie van de tweede generatie, is digitaal erfgoed

Wikisage is op 1 na de grootste internet-encyclopedie in het Nederlands. Iedereen kan de hier verzamelde kennis gratis gebruiken, zonder storende advertenties. De Koninklijke Bibliotheek van Nederland heeft Wikisage in 2018 aangemerkt als digitaal erfgoed.

  • Wilt u meehelpen om Wikisage te laten groeien? Maak dan een account aan. U bent van harte welkom. Zie: Portaal:Gebruikers.
  • Bent u blij met Wikisage, of wilt u juist meer? Dan stellen we een bescheiden donatie om de kosten te bestrijden zeer op prijs. Zie: Portaal:Donaties.
rel=nofollow

Kotlin (programmeertaal): verschil tussen versies

Uit Wikisage
Naar navigatie springen Naar zoeken springen
(https://nl.wikipedia.org/w/index.php?title=Kotlin_(programmeertaal)&oldid=49924942 12 sep 2017 Tieskedh 11 mei 2017)
 
(https://nl.wikipedia.org/w/index.php?title=Kotlin_(programmeertaal)&oldid=49956086 15 sep 2017)
 
Regel 3: Regel 3:
| logo=Kotlin-logo.png
| logo=Kotlin-logo.png
| extensies=.kt, .kts
| extensies=.kt, .kts
| paradigma=[[Multi-paradigmaprogrammeertaal|Multi-paradigma]]: [[Functionele programmeertaal|functioneel]], [[objectgeorienteerd]], [[Imperatief programmeren
| paradigma=[[Multi-paradigmaprogrammeertaal|Multi-paradigma]]: [[Functionele programmeertaal|functioneel]], [[objectgeorienteerd]], [[Imperatief programmeren]]
| imperatief]]
| jaar=2011
| jaar=2011
| ontwerper=Andrey Breslav
| ontwerper=Andrey Breslav
| ontwikkelaar=JetBrains en open source contributors
| ontwikkelaar=JetBrains en open source contributors
| versie=Kotlin 1.1.2
| versie=1.1.2
| typesystem=statisch, sterk met type-ingferentie
| typesystem=statisch, sterk met [[type-inferentie]]
}}
}}
'''Kotlin''' is een [[Typesysteem#Statische typering|statisch getypeerde]] [[multiplatform]]-[[programmeertaal]], die probeert volledig [[Interoperabiliteit|interoperabel]] te zijn met de taal van het platform.<ref name=":0">{{Citeer web|url=https://zeroturnaround.com/rebellabs/jvm-languages-report-extended-interview-with-kotlin-creator-andrey-breslav/|titel=JVM Languages Report: Interview with Kotlin Creator|bezochtdatum=2017-05-10|werk=zeroturnaround.com|taal=en}}</ref>
'''Kotlin''' is een [[Typesysteem#Statische typering|statisch getypeerde]] [[multiplatform]]-[[programmeertaal]], die probeert volledig [[Interoperabiliteit|interoperabel]] te zijn met de taal van het platform.<ref name=":0">{{Citeer web|url=https://zeroturnaround.com/rebellabs/jvm-languages-report-extended-interview-with-kotlin-creator-andrey-breslav/|titel=JVM Languages Report: Interview with Kotlin Creator|bezochtdatum=2017-05-10|werk=zeroturnaround.com|taal=en}}</ref>
Regel 16: Regel 15:


== Filosofie ==
== Filosofie ==
Andrey Breslav (hoofdingenieur van JetBrains) verklaarde dat Kotlin is ontwikkeld om een in industriële object georiënteerd taal te zijn, die "beter" is dan Java, maar toch volledig interoperabel met java, zodat bedrijven een geleidelijke overstap kunnen maken naar Kotlin<ref name=":0" />.
Het oorspronkelijke doel van Kotlin is om een [[Objectgeoriënteerd|object georiënteerd]] taal te zijn, die "beter" is dan Java, maar toch volledig interoperabel met Java. Hierdoor kunnen bedrijven een geleidelijke overstap maken naar Kotlin, aldus Andrey Breslav (hoofdingenieur van JetBrains)<ref name=":0" />.


Nu wil Kotlin op meerdere platformen zijn, zodat uiteindelijk een heel systeem - van de server back-end tot de mobiele front-end - in Kotlin geschreven kan zijn. Daarnaast wil Kotlin codehergebruik door verschillende platformen mogelijk maken<ref>{{Citeer web|url=https://blog.jetbrains.com/kotlin/2017/04/kotlinnative-tech-preview-kotlin-without-a-vm/|titel=Kotlin/Native Tech Preview: Kotlin without a VM|bezochtdatum=2017-05-18|datum=2017-04-04|werk=Kotlin Blog|taal=en}}</ref>.
Sinds 2017 is het doel van Kotlin verbreed en wil het een [[multiplatform]] taal zijn die compileert naar de [[native]] talen van het platform, en hierdoor compatibel is met die talen<ref>{{Citeer web|url=https://blog.jetbrains.com/kotlin/2017/04/kotlinnative-tech-preview-kotlin-without-a-vm/|titel=Kotlin/Native Tech Preview: Kotlin without a VM|bezochtdatum=2017-05-18|datum=2017-04-04|werk=Kotlin Blog|taal=en}}</ref>.


== Platforms ==
== Platforms ==
Kotlin is bezig om te compileren naar meer platforms. Hierbij is het uiteindelijke doel dat alle componenten van een ICT-systeem in Kotlin gebouwd kunnen worden. In tegenstelling tot de JVM wil Kotlin compileren naar verschillende talen.
De Kotlin-[[Application programming interface|API]] is opgesplitst in twee onderdelen:


Kotlin wil de API opsplitsen in twee onderdelen. De ''common modules'' en de platform specifieke modules. De API van de common modules zou door de compilers van elk platform worden geïmplementeerd. Als iets is gebouwd waarbij alleen gebruik is gemaakt van de common modules,  kan dit naar elk platform worden gecompileerd en daar worden gebruikt.
de ''common modules'' en de ''platform specifieke'' modules.


De platform-specifieke functies worden verzameld in de platform-specifieke modules.
In de common modules zitten de onderdelen die vanaf elk platform te gebruiken zijn en de platform-gerelateerde onderdelen zitten in de platform-specifieke onderdelen.


=== Java virtual machine ===
Wanneer iets dus geschreven is met alleen de common modules, dan kan dit worden gecompileerd naar elk platform.
Kotlin (althans, de geproduceerde bytecode) draait op de [[Java Virtual Machine]]. Hierbij kan worden gekozen tussen twee versies van Java: Java 6 en Java 8.
 
=== Java Virtual Machine ===
De door Kotlin geproduceerde bytecode draait op de [[Java Virtual Machine]]. Hierbij kan worden gekozen tussen Java 6 en Java 8.


Voor de implementatie van de common modules wordt gebruik gemaakt van de Java Class Library en de Java Collections Framework.
Voor de implementatie van de common modules wordt gebruik gemaakt van de Java Class Library en de Java Collections Framework.


Om te compileren is sinds versie 1.1.2 is wel [[Java Development Kit|JDK]]8 nodig.
Om te compileren is sinds versie 1.1.2 [[Java Development Kit|JDK]]8 nodig.


=== Android ===
=== Android ===
Op 17 mei 2017 heeft [[Android (besturingssysteem)|Android]] Kotlin als officiële programmeertaal toegevoegd<ref>{{Citeer web|url=https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/|titel=Kotlin on Android. Now official|bezochtdatum=2017-05-18|datum=2017-05-17|werk=Kotlin Blog|taal=en}}</ref>.  
Op 17 mei 2017 heeft [[Android (besturingssysteem)|Android]] Kotlin als officiële programmeertaal toegevoegd<ref>{{Citeer web|url=https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/|titel=Kotlin on Android. Now official|bezochtdatum=2017-05-18|datum=2017-05-17|werk=Kotlin Blog|taal=en}}</ref>.


De bekendste kotlin-framework voor Android is [https://github.com/Kotlin/anko Anko], die ontwikkeld is door Jetbrains.
De bekendste kotlin-framework voor Android is [https://github.com/Kotlin/anko Anko], die ontwikkeld is door Jetbrains.


=== Javascript ===
=== Javascript ===
Kotlin/JavaScript wordt getranspileerd naar [[JavaScript]].  
Kotlin/JavaScript wordt getranspileerd naar [[JavaScript]]. Momenteel is dat [[ECMAScript]] 5.1.
 
Op dit moment is de target  [[ECMAScript]] 5.1, maar er zijn plannen om ECMAScript 2015 te ondersteunen.  


Daarnaast kan [[TypeScript]] definities naar Kotlin declaraties worden geconverteerd met [https://github.com/kotlin/ts2kt ts2kt].
Daarnaast kan [[TypeScript]] definities naar Kotlin declaraties worden geconverteerd met [https://github.com/kotlin/ts2kt ts2kt].


=== Native ===
=== Native ===
Met de [http://llvm.org/ LLVM compiler] wordt code direct naar machinecode vertaald. Het Native project is nog in een previewstadium.
Met de [http://llvm.org/ LLVM compiler] wordt code direct naar machinecode vertaald. Het Native project is nog in een previewstadium.


De platformen die worden ondersteund omvatten:
De platformen die worden ondersteund omvatten:
Regel 60: Regel 59:


== Semantiek ==
== Semantiek ==
Kotlin ondersteund het [[Objectgeoriënteerd|Object Georiënteerd programmeren]] door middel van [[Klasse (informatica)|klassen]] en [[Methode (objectoriëntatie)|methodes]], maar de methodes kunnen ook worden gebruikt buiten de klassen, waardoor [[imperatief programmeren]] met functies ook mogelijk is<ref>{{Citeer web|url=https://kotlinlang.org/docs/reference/functions.html|titel=Functions - Kotlin Programming Language|bezochtdatum=2017-05-10|werk=Kotlin}}</ref>. Een programma begint net als Java met de functie ''main'' met als parameter een array met [[Command-line-interface|command-line]]-argumenten. Type-inferentie is ook mogelijk.
Kotlin ondersteunt het [[Objectgeoriënteerd|Object Georiënteerd programmeren]] door middel van [[Klasse (informatica)|klassen]] en [[Methode (objectoriëntatie)|methodes]], maar de methodes kunnen ook worden gebruikt buiten de klassen, waardoor [[imperatief programmeren]] met functies ook mogelijk is<ref>{{Citeer web|url=https://kotlinlang.org/docs/reference/functions.html|titel=Functions - Kotlin Programming Language|bezochtdatum=2017-05-10|werk=Kotlin}}</ref>. Een programma begint net als Java met de functie ''main'' met als parameter een array met [[Command-line-interface|command-line]]-argumenten. Type-inferentie is ook mogelijk.


Hello world! voorbeeld:<syntaxhighlight lang="kotlin">
Hello world! voorbeeld:<syntaxhighlight lang="kotlin">
Regel 70: Regel 69:


=== Nullable types ===
=== Nullable types ===
Kotlin maakt verschil nullable types en niet-nullable types. alle Nullable types moeten eindigen met een "?":<syntaxhighlight lang="kotlin">
Kotlin maakt verschil tussen nullable types en niet-nullable types. alle Nullable types moeten eindigen met een "?":<syntaxhighlight lang="kotlin">
val nullString:    String? = null  //werkt, want is nullable
val nullString:    String? = null  //werkt, want is nullable
val notNullString:  String  = null  //werkt niet want is niet nullable
val notNullString:  String  = null  //werkt niet want is niet nullable
</syntaxhighlight>Voor elke aanroep op een nullable type moet worden gekeken of de type null is.  
</syntaxhighlight>Voor elke aanroep op een nullable type moet worden gekeken of de type null is.


In Kotlin zijn hier twee operatoren voor:
In Kotlin zijn hier twee operatoren voor:
Regel 103: Regel 102:
Een van de opvallende regels van Kotlin zijn DSL-builders. Hiermee kan een DSL worden gemaakt.
Een van de opvallende regels van Kotlin zijn DSL-builders. Hiermee kan een DSL worden gemaakt.


[[Domain Specific Language|DSL]] (Domain specific language) is een taal die ontwikkeld is voor bepaalde domeinen.  
[[Domain Specific Language|DSL]] (Domain specific language) is een taal die ontwikkeld is voor bepaalde domeinen.


Deze DSL-functies bestaan uit extensie-functies en regels voor lambda's die gecombineerd de extensie-lambda vormen.
Deze DSL-functies bestaan uit extensie-functies en regels voor lambda's die gecombineerd de extensie-lambda vormen.
Regel 122: Regel 121:
     // we zitten in de RekenMachine, dus this is de RekenMachine
     // we zitten in de RekenMachine, dus this is de RekenMachine
      
      
     // maar this  mag worden weggelaten dus:
     // maar dit mag worden weggelaten dus:
     keer(5, a)
     keer(5, a)
}
}
Regel 142: Regel 141:
//  - een lambda die een integer vraagt en een integer teruggeeft
//  - een lambda die een integer vraagt en een integer teruggeeft
fun keer(a: Int, keer: (Int)->Int) : a {
fun keer(a: Int, keer: (Int)->Int) : a {
     return keer(a) // voert de lambda uit op de twee gekregen integers
     return keer(a) // voert de lambda uit op de twee gekregen integers
}
}


Regel 148: Regel 147:
     // lambda opgeslagen in veriabele
     // lambda opgeslagen in veriabele
     val keer5 = {a -> a * 5}
     val keer5 = {a -> a * 5}
     keer(3, keer5) // is 15
     keer(3, keer5) // is 15
      
      
     //lambda direct als parameter
     //lambda direct als parameter
Regel 172: Regel 171:
fun main(args: Array<String>){
fun main(args: Array<String>){
     //lambda opgeslage in variabele
     //lambda opgeslage in variabele
     val keer5 = {  
     val keer5 = {
         Rekenmachine.a * 5
         Rekenmachine.a * 5
     }
     }
Regel 206: Regel 205:
fun bereken(berekening: Rekenmachine.()->Int) : Int{
fun bereken(berekening: Rekenmachine.()->Int) : Int{
     val rm: Rekenmachine = Rekenmachine() //maak Rekenmachine aan.
     val rm: Rekenmachine = Rekenmachine() //maak Rekenmachine aan.
     return lambda(rm)       // geef rm aan de lambda
     return lambda(rm) // geef rm aan de lambda
}
}


Regel 245: Regel 244:


{{Appendix}}
{{Appendix}}
{{authority control|TYPE=w|Wikidata=Q3816639 }}
[[Categorie:Programmeertaal]]
[[Categorie:Programmeertaal]]

Huidige versie van 25 sep 2017 om 23:34

rel=nofollow

Kotlin is een statisch getypeerde multiplatform-programmeertaal, die probeert volledig interoperabel te zijn met de taal van het platform.[1]

Kotlin is ontwikkeld door JetBrains, dat gevestigd is in Sint-Petersburg en vernoemd naar het nabijgelegen eiland Kotlin.[2]

Filosofie

Het oorspronkelijke doel van Kotlin is om een object georiënteerd taal te zijn, die "beter" is dan Java, maar toch volledig interoperabel met Java. Hierdoor kunnen bedrijven een geleidelijke overstap maken naar Kotlin, aldus Andrey Breslav (hoofdingenieur van JetBrains)[1].

Sinds 2017 is het doel van Kotlin verbreed en wil het een multiplatform taal zijn die compileert naar de native talen van het platform, en hierdoor compatibel is met die talen[3].

Platforms

De Kotlin-API is opgesplitst in twee onderdelen:

de common modules en de platform specifieke modules.

In de common modules zitten de onderdelen die vanaf elk platform te gebruiken zijn en de platform-gerelateerde onderdelen zitten in de platform-specifieke onderdelen.

Wanneer iets dus geschreven is met alleen de common modules, dan kan dit worden gecompileerd naar elk platform.

Java Virtual Machine

De door Kotlin geproduceerde bytecode draait op de Java Virtual Machine. Hierbij kan worden gekozen tussen Java 6 en Java 8.

Voor de implementatie van de common modules wordt gebruik gemaakt van de Java Class Library en de Java Collections Framework.

Om te compileren is sinds versie 1.1.2 JDK8 nodig.

Android

Op 17 mei 2017 heeft Android Kotlin als officiële programmeertaal toegevoegd[4].

De bekendste kotlin-framework voor Android is Anko, die ontwikkeld is door Jetbrains.

Javascript

Kotlin/JavaScript wordt getranspileerd naar JavaScript. Momenteel is dat ECMAScript 5.1.

Daarnaast kan TypeScript definities naar Kotlin declaraties worden geconverteerd met ts2kt.

Native

Met de LLVM compiler wordt code direct naar machinecode vertaald. Het Native project is nog in een previewstadium.

De platformen die worden ondersteund omvatten:

  • Mac OS X 10.10 and later (x86-64)
  • x86-64 Ubuntu Linux (14.04, 16.04 and later), other Linux flavours may work as well
  • Apple iOS (arm64), cross-compiled on MacOS X host
  • Raspberry Pi, cross-compiled on Linux host

Kotlin/Native kan interfacen met in C geschreven functies.

Syntaxis

In Kotlin komt het datatype na de naam van de variabelen en parameters. Daarnaast is de puntkomma om een statement af te sluiten niet verplicht; meestal is een nieuwe regel voor de compiler al genoeg[5].

Semantiek

Kotlin ondersteunt het Object Georiënteerd programmeren door middel van klassen en methodes, maar de methodes kunnen ook worden gebruikt buiten de klassen, waardoor imperatief programmeren met functies ook mogelijk is[6]. Een programma begint net als Java met de functie main met als parameter een array met command-line-argumenten. Type-inferentie is ook mogelijk.

Hello world! voorbeeld:<syntaxhighlight lang="kotlin"> fun main(args: Array<String>) {

   val scope = "world"
   println("hello, $scope")

} </syntaxhighlight>

Nullable types

Kotlin maakt verschil tussen nullable types en niet-nullable types. alle Nullable types moeten eindigen met een "?":<syntaxhighlight lang="kotlin"> val nullString: String? = null //werkt, want is nullable val notNullString: String = null //werkt niet want is niet nullable </syntaxhighlight>Voor elke aanroep op een nullable type moet worden gekeken of de type null is.

In Kotlin zijn hier twee operatoren voor:

  • ?. (veilige-navigatie-operator): Hij geeft null terug als de operand null is en hij voert anders de code achter de operator uit.
  • ?: (Elvis-operator) : geeft de waarde voor de operator als die niet null is, anders geeft hij de waarde achter de operator.

Voorbeeld van de veilige-navigatie-operator:<syntaxhighlight lang="kotlin"> // geeft null als foo of bar null zijn en geeft anders de teruggeefwaarde van baz foo ?. bar() ?. baz() </syntaxhighlight>Voorbeeld van de Elvis-operator<syntaxhighlight lang="kotlin"> fun welkom(naam: String?){

   val welkomNaam = naam ?: "vreemdeling"

}

fun main(args : Array<String>){

   println(welkom(null)) // print "welkom vreemdeling"
   println(welkom("gebruiker")) // print "welkom gebruiker"

}

</syntaxhighlight>Om dependency injection mogelijk te maken zonder een nullable type te gebruiken, kan er gebruikt worden gemaakt van lateinit.

Coroutines

Coroutines is Kotlins manier voor multithreading. Het opvallende is dat Kotlin hier maar een keywoord voor gebruikt: Suspend.

Daarnaast wordt er veel gedaan met compiler-magic, waardoor de coroutines veel lichter zijn dan threads.

Op dit moment zijn de coroutines nog in de experimentele fase.

DSL builders

Een van de opvallende regels van Kotlin zijn DSL-builders. Hiermee kan een DSL worden gemaakt.

DSL (Domain specific language) is een taal die ontwikkeld is voor bepaalde domeinen.

Deze DSL-functies bestaan uit extensie-functies en regels voor lambda's die gecombineerd de extensie-lambda vormen.

Extensie-functies

Kotlin kent het concept extensie-functies. Dit zijn functies die een al bestaande klasse kunnen uitbreiden.

Voorbeeld van extensie-functies:<syntaxhighlight lang="kotlin"> class RekenMachine{

   fun keer(a: Int, b: Int)  : Int{
       return a * b
   }

}

//voegt keer5 aan RekenMachine toe fun RekenMachine.keer5(a: Int, b: Int){

   this.keer(5, a)
   // we zitten in de RekenMachine, dus this is de RekenMachine
   
   // maar dit mag worden weggelaten dus:
   keer(5, a)

}

fun main(args : Array<String>){

   // hier wordt een nieuw RekenMachine aangemaakt
   // (de "new" van Java moet in Kotlin worden weggelaten)
   // en keer op aangeroepen
   RekenMachine().keer5(3) // antwoord: 15

} </syntaxhighlight>

Lambda's

Lambda is de naam voor een functie-datatype.In Kotlin, wordt een lambda geschreven als (parameter, parameter) -> returnType. Wanneer lambda's als laatste parameter worden meegegeven aan een functie, mag hij achter de functie worden neergezet. Bovendien mogen als er achter een functie-aanroep wordt gedaan, zonder parameters, mogen de haakjes weggehaald worden.

Voorbeeld met meerdere parameters:<syntaxhighlight lang="kotlin"> // deze functies wil drie parameters // - een integer // - een lambda die een integer vraagt en een integer teruggeeft fun keer(a: Int, keer: (Int)->Int) : a {

   return keer(a) // voert de lambda uit op de twee gekregen integers

}

fun main(args: array<String>){

   // lambda opgeslagen in veriabele
   val keer5 = {a -> a * 5}
   keer(3, keer5) // is 15
   
   //lambda direct als parameter
   keer(3, {a -> a * 5})
   
   //lambda achter de functie
   keer(3) {
       a -> a * 5
   }

} </syntaxhighlight>Voorbeeld met een parameter:<syntaxhighlight lang="kotlin"> // Unit (void in Java) // vraagt een lambda zonder parameters die Unit (niks) teruggeeft class Rekenmachine{

   var a = 3
   
   fun keer(exec: ()-> int): Int{
       return exec()
   }

}


fun main(args: Array<String>){

   //lambda opgeslage in variabele
   val keer5 = {
       Rekenmachine.a * 5
   }
   keer(keer5)
   
   //lambda meegegeven als parameter
   keer({
       Rekenmachine.a * 5
   }) 
   
   //lambda achter de functie
   keer(){
       Rekenmachine.a * 5
   }
   
   // er zijn geen parameters tussen de haakjes,dus de haakjes mogen weg
   keer{
       Rekenmachine.a * 5
   }

} </syntaxhighlight>

Extensie-lambda's

In Kotlin heb je niet alleen extensie-functies maar ook extensie-lambda's. Deze worden meegegeven als een parameter:<syntaxhighlight lang="kotlin"> class Rekenmachine{

   var a: Int = 3
   fun keer(exec: ()-> int) : Int {
       return exec();
   }

}

// Rekenmachine.() vraagt om een extension-lambda, die een int returnt fun bereken(berekening: Rekenmachine.()->Int) : Int{

   val rm: Rekenmachine = Rekenmachine() //maak Rekenmachine aan.
   return lambda(rm) // geef rm aan de lambda

}

fun main(args: Array<String>) {

   //zonder extension-lambda zie vorig voorbeeld
   Rekenmachine().keer{
       Rekenmachine.a * 5
   }
   
   
   
   
   bereken(//hieronder begint de extension-lambda:
       {//this wijst naar rekenmachine, want we zitten in rekenmachie
           this.keer{
               this.a * 5
           }
       }
   )
   
   bereken(//hieronder begint de extension-lambda:
       {//this mag worden weggelaten
           keer{a * 5}
       }
   )
   
   // de extension-lambda was de laatste parameter,dus hetvolgende maag ook:
   bereken{
       keer{a * 5}
   }
   
   // keer geeft 3 * 5 = 15 terug en bereken geeft die door.
   val ans = bereken{
       keer{a*5}
   }

} </syntaxhighlight>

Bronnen, noten en/of referenties

Bronnen, noten en/of referenties
  1. 1,0 1,1 (en) JVM Languages Report: Interview with Kotlin Creator. zeroturnaround.com Geraadpleegd op 2017-05-10
  2. º The Advent of Kotlin: A Conversation with JetBrains' Andrey Breslav. www.oracle.com Geraadpleegd op 2017-05-10
  3. º (en) Kotlin/Native Tech Preview: Kotlin without a VM. Kotlin Blog (2017-04-04) Geraadpleegd op 2017-05-18
  4. º (en) Kotlin on Android. Now official. Kotlin Blog (2017-05-17) Geraadpleegd op 2017-05-18
  5. º Kotlin Programming Language. Kotlin Geraadpleegd op 2017-05-10
  6. º Functions - Kotlin Programming Language. Kotlin Geraadpleegd op 2017-05-10
rel=nofollow
rel=nofollow
rel=nofollow