8000 GitHub - smougenot/KotlinDemo
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

smougenot/KotlinDemo

Repository files navigation

Kotlin Demo + Spring Boot

Code Factor Workflow build Workflow release

Objectif

Présentation succincte de Kotlin, mise oeuvre autour de Spring Boot, JPA et REST

Initialisation

À partir de start.spring.io with Gradle, Kotlin, Java 11
Du code repris depuis les documentations référencées.
Du code inspiré par les TPs de la JAcadémie.

Kotlin en quelques mots

  • Kotlin pour serveur (~Java)

    • Compilé en .class

  • Kotlin Android

    • Cité pour la classe

  • Kotlin Javascript

    • Compilé en .js (ES5)

  • Kotlin Native

    • Compilé en binaire (pour l’OS)

Généralité

  • Plus lisible

  • Moins de code

  • Plus de vérifications à la compilation

  • Beaucoup de bonnes pratiques

  • Tourne dans la JVM (interopérable)

Goodies

  • oublie le ; en fin d’instruction

  • oublie l’opérateur' new

  • les attributs sont public par défaut

  • oublie les accesseurs (même si on les utilisent)

Variable : Mutabilité explicite

Immutable

val maConstante = "Never change me"
val mesChoix = setOf("ras")

Mutable

var maConstante = "Can change"
maConstante = "toto"

val mesChoix = mutableSetOf("ci")
mesChoix.add("ou ça")

Fonction

fun nom(param: String): String {
  return "the result "
}

fun sum(a: Int, b: Int) = a + b

fun printSum(a: Int, b: Int): Unit {
    println("sum of $a and $b is ${a + b}")
}

Également possible à l’extérieur d’une classe

Null safe : à la compilation

fun nom(nullable: String?, nonNull: String) {
  // nullable.length // do not compile
  nullable!!.length
}

fun nom(files: String?) {
  // accède à size si files est non null
  // valeur par défaut (files==null ||  files.size==null)
  println(files?.length ?: "empty")
}

Auto cast

fun getStringLength(obj: Any): Int? {
    if (obj is String) {
        // `obj` is automatically cast to `String` in this branch
        return obj.length
    }

    // `obj` is still of type `Any` outside of the type-checked branch
    return null
}

Classe

  • Multiples classes par fichier source

  • Pas forcément de corps

  • Finale par défaut

open class ParentClass(val size: Int) {
    fun wontOverride() {
        // ...
    }

    open fun canOverride() {
        // ...
    }
}

class DescendantClass(aSize: Int) : ParentClass(aSize) {
    override fun canOverride() {
        // ...
    }
}

fun f() {
    val numberFour = DescendantClass(4)
}

Data class

  • Pojo

  • Immutable

  • Finale

Paramètre nommés, valeurs par défaut

data class MessageK(
  val from: String,
  val to: String,
  val title: String? = null,
  val cc: String? = null,
  val body: String? = null
)

val t = MessageK(from="From", to="To", cc="Cc")

String

Interpolation de variable

val qui="who"
val msg="${qui.toUpperCase()} est sur la première base"

Multi-ligne littérale

val texte = """
    Lorem ipsum dolor sit amet,
    consectetur adipiscing elit,
    sed do eiusmod tempor incididunt
    ut labore et dolore magna aliqua.
""".trimIndent()

Destructuration

  • Projette le contenu d’un objet dans plusieurs variables.

  • Attention à l’ordre

  • Va bien avec une data class

for ((key, value) in map) {
// do something with the key and the value
}
val numbers = listOf("one", "two", "three", "four")
val (match, rest) = numbers.partition { it.length > 3 }

Extension

  • Ajouter des méthodes à une classe existante

fun String.asKebab() = this.replace(' ', '-')

assertThat("a Bc d".asKebab()).isEqualTo("a-Bc-d")
  • Ajouter des attributs (~getter) à une classe existante

e.g. Ajouter un attribut indiquant le plus haut index de position dans une liste
sur toutes les listes (via un getter)

val <T> List<T>.lastIndex: Int
    get() = size - 1

var maListe = listOf("1", "2", "3")
maListe.lastIndex // is 2

Function de niveau supérieur

  • Une fonction qui prend en paramètre une fonction

  • lambda comme en Java

Exemple l’extension fold fournie sur les collections

fun <T, R> Collection<T>.fold(
    initial: R,
    combine: (acc: R, nextElement: T) -> R // (1)
): R {
    var accumulator: R = initial
    for (element: T in this) {
        accumulator = combine(accumulator, element)
    }
    return accumulator
}
  1. Signature d’une fonction

Utilisation

val items = listOf(1, 2, 3, 4, 5)

// Lambdas are code blocks enclosed in curly braces.
items.fold(0, {
  // When a lambda has parameters, they go first, followed by '->'
  acc: Int, i: Int ->
    print("acc = $acc, i = $i, ")
    val result = acc + i
    println("result = $result")
    // The last expression in a lambda is considered the return value:
    result
})

Mais aussi

  • alias de type

typealias ID = Long?

@Entity
class Student(
        var name: String,
        @Id @GeneratedValue var id: ID = null)
  • scope function

val adam = Person("Adam").apply {
    age = 20  // same as this.age = 20 or adam.age = 20
    city = "London"
}
  • when

when (x) {
    is Int -> print(x + 1)
    is String -> print(x.length + 1)
    is IntArray -> print(x.sum())
}
  • Type-Safe Builders

fun result() =
    html {
        head {
            title {+"XML encoding with Kotlin"}
        }
    //...
    }

fun html(init: HTML.() -> Unit): HTML {
    val html = HTML()
    html.init()
    return html
}
  • Coroutines (thread légers) …​

JPA

  • open plugin allopen

  • Mutable

    • val → var

    • Set → MutableSet

Test unitaire (Spring, MockBean)

  • Nom de Méthode \`ma methode\`

Test d’intégration Web

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages

0