Guide de style Kotlin

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Ce document vise à définir l'ensemble des normes de codage Android de Google pour le langage de programmation Kotlin. Le code source Kotlin est considéré comme conforme à ces normes si, et seulement si, il respecte les règles décrites ci-dessous.

Comme dans d'autres guides de style de programmation, les sujets abordés ne portent pas seulement sur l'aspect esthétique de la mise en forme du code, mais également sur d'autres types de conventions ou de normes de codage. Cependant, ce document se concentre principalement sur la définition des règles strictes que nous appliquons partout, et évite de fournir des recommandations qui peuvent être mal implémentées (que ce soit par un humain ou un outil).

Dernière mise à jour : 19-05-2021

Fichiers sources

Tous les fichiers sources doivent être encodés en UTF-8.

Dénominations

Si un fichier source ne contient qu'une seule classe de niveau supérieur, le nom du fichier doit utiliser le nom sensible à la casse et se terminer par l'extension .kt. Si un fichier source contient plusieurs déclarations de niveau supérieur, choisissez un nom décrivant le contenu du fichier, écrit en PascalCase et suivi par l'extension .kt.

// MyClass.kt
class MyClass { }
// Bar.kt
class Bar { }
fun Runnable.toBar(): Bar = // …
// Map.kt
fun <T, O> Set<T>.map(func: (T) -> O): List<O> = // …
fun <T, O> List<T>.map(func: (T) -> O): List<O> = // …

Caractères spéciaux

Espaces blancs

Hormis la séquence de caractères de fin de ligne, le caractère d'espace ASCII horizontal (0x20) est le seul caractère d'espace blanc trouvé dans le fichier source. Cela signifie que :

  • tous les autres types d'espaces blancs dans les littéraux de chaîne et de caractère sont échappés ;
  • les caractères de tabulation ne sont pas utilisés pour les retraits.

Séquences d'échappement spéciales

Pour les caractères pour lesquels il existe une séquence d'échappement spéciale (\b, \n, \r, \t, \', \", \\ et \$), celle-ci doit être utilisée à la place du code Unicode correspondant (par exemple \u000a).

Caractères non ASCII

Pour les autres caractères non ASCII, utilisez le caractère Unicode (par exemple, ) ou la séquence d'échappement Unicode équivalente (par exemple, \u221e). Le choix dépend uniquement de ce qui rend le code plus facile à lire et à comprendre. Les échappements Unicode sont déconseillés pour les caractères imprimables, quel que soit l'emplacement, et fortement déconseillés en dehors des littéraux de chaîne et des commentaires.

Exemple Discussion
val unitAbbrev = "μs" Excellent : parfaitement clair même sans commentaire.
val unitAbbrev = "\u03bcs" // μs Mauvais : il n'y a aucune raison d'utiliser une séquence d'échappement pour un caractère imprimable.
val unitAbbrev = "\u03bcs" Mauvais : le lecteur n'a aucune idée de ce que c'est.
return "\ufeff" + content Bon : utilisez des caractères d'échappement pour les caractères non imprimables et ajoutez des commentaires si nécessaire.

Structure

Un fichier .kt comprend les éléments suivants (dans l'ordre indiqué) :

  • En-tête sur la licence et/ou les droits d'auteur (facultatif)
  • Annotations au niveau du fichier
  • Déclaration de package
  • Instructions d'importation
  • Déclarations de niveau supérieur

Une ligne vide sépare chacune de ces sections.

Si le fichier contient un en-tête de droits d'auteur ou de licence, celui-ci doit être placé tout en haut du fichier dans un commentaire multiligne.

/*
 * Copyright 2017 Google, Inc.
 *
 * ...
 */
 

N'utilisez pas de commentaire sur une seule ligne ou KDoc.

/**
 * Copyright 2017 Google, Inc.
 *
 * ...
 */
// Copyright 2017 Google, Inc.
//
// ...

Annotations au niveau du fichier

Les annotations avec la cible d'utilisation "file" sont placées entre tout commentaire d'en-tête et la déclaration de package.

Déclaration de package

La déclaration de package n'est soumise à aucune limite de colonne et n'est jamais encapsulée.

Instructions d'importation

Les instructions d'importation des classes, des fonctions et des propriétés sont regroupées dans une liste unique dans l'ordre de tri des caractères ASCII.

Les importations de caractères génériques (quel que soit leur type) ne sont pas autorisées.

Tout comme les déclarations de package, les instructions d'importation ne sont pas soumises à une limite de colonne et ne sont jamais encapsulées.

Déclarations de niveau supérieur

Un fichier .kt peut déclarer un ou plusieurs types, fonctions, propriétés ou alias de type de niveau supérieur.

Le contenu d'un fichier doit porter sur un seul sujet. Il peut s'agir, par exemple, d'un seul type public ou d'un ensemble de fonctions d'extension effectuant la même opération sur plusieurs types de récepteurs. Les déclarations portant sur des sujets différents doivent être placées dans des fichiers distincts, et les déclarations publiques dans le même fichier doivent être réduites au minimum.

Aucune restriction explicite n'est appliquée au nombre ou à l'ordre des contenus d'un fichier.

Les fichiers sources sont généralement lus de haut en bas, ce qui signifie que, d'une manière générale, l'ordre doit refléter le fait que les déclarations placées plus haut permettent de mieux comprendre les suivantes. Le contenu de chaque fichier peut être organisé différemment. De même, un fichier peut contenir 100 propriétés, un autre 10 fonctions et un autre une seule classe.

Ce qui est important, c'est que chaque fichier utilise un certain ordre logique, que son mainteneur pourrait expliquer, si on le lui demandait. Par exemple, les nouvelles fonctions ne sont pas simplement ajoutées à la fin du fichier, car cela donnerait un ordre chronologique selon la date d'ajout, qui n'est pas un ordre logique.

Ordre des membres de classe

L'ordre des membres d'une classe suit les mêmes règles que les déclarations de niveau supérieur.

Mise en forme

Accolades

Les accolades ne sont pas obligatoires pour les branches when et les expressions if qui n'ont pas plus d'une branche else et ne contiennent qu'une seule ligne.

if (string.isEmpty()) return

val result =
    if (string.isEmpty()) DEFAULT_VALUE else string

when (value) {
    0 -> return
    // …
}

Elles sont nécessaires pour les instructions et expressions if, for, when branch, do et while, même si le corps est vide ou qu'il ne contient qu'une seule instruction.

if (string.isEmpty())
    return  // WRONG!

if (string.isEmpty()) {
    return  // Okay
}

if (string.isEmpty()) return  // WRONG
else doLotsOfProcessingOn(string, otherParametersHere)

if (string.isEmpty()) {
    return  // Okay
} else {
    doLotsOfProcessingOn(string, otherParametersHere)
}

Blocs non vides

Les accolades suivent le style Kernighan et Ritchie ("crochets égyptiens") pour les blocs non vides et les éléments de type bloc :

  • Pas de saut de ligne avant l'accolade.
  • Saut de ligne après l'accolade ouvrante.
  • Saut de ligne avant l'accolade fermante.
  • Saut de ligne après l'accolade fermante uniquement si elle termine une instruction ou le corps d'une fonction, d'un constructeur ou d'une classe nommée. Par exemple, il n'y a pas de saut de ligne après l'accolade si elle est suivie d'une virgule ou de else.
return Runnable {
    while (condition()) {
        foo()
    }
}

return object : MyClass() {
    override fun foo() {
        if (condition()) {
            try {
                something()
            } catch (e: ProblemException) {
                recover()
            }
        } else if (otherCondition()) {
            somethingElse()
        } else {
            lastThing()
        }
    }
}

Vous trouverez ci-dessous quelques exceptions pour les classes d'énumération.

Blocs vides

Un bloc vide ou un élément de type bloc doit être de style K&R.

try {
    doSomething()
} catch (e: Exception) {} // WRONG!
try {
    doSomething()
} catch (e: Exception) {
} // Okay

Expressions

Un bloc conditionnel if/else utilisé en tant qu'expression peut être sans accolades uniquement s'il tient sur une seule ligne.

val value = if (string.isEmpty()) 0 else 1  // Okay
val value = if (string.isEmpty())  // WRONG!
    0
else
    1
val value = if (string.isEmpty()) { // Okay
    0
} else {
    1
}

Retrait

À chaque nouveau bloc ou élément de type bloc, le retrait est augmenté de quatre espaces. Lorsque le bloc est fermé, le retrait revient au niveau précédent. Le niveau de retrait s'applique au code et aux commentaires du bloc.

Une seule instruction par ligne

Chaque instruction est suivie d'un saut de ligne. Aucun point-virgule n'est utilisé.

Renvoi à la ligne

Le code est limité à 100 caractères par colonne. Sauf indication contraire ci-dessous, les lignes qui dépassent cette limite doivent être encapsulées, comme expliqué plus bas.

Exceptions :

  • Lignes ne pouvant pas respecter la limite de colonnes (par exemple, une URL longue dans KDoc)
  • Instructions package et import
  • Lignes de commande dans un commentaire pouvant être coupées et collées dans une interface système

Où faire un saut de ligne

La première règle à respecter pour les renvois à la ligne est la suivante : il est préférable de faire le saut de ligne à un niveau syntaxique plus élevé. En outre :

  • Pour les opérateurs et les fonctions infixe, le saut de ligne se fait après le nom de l'opérateur ou de la fonction infixe.
  • Le saut de ligne précède le symbole pour les symboles de type opérateur suivants :
    • Le point de séparation (., ?.)
    • Le double deux-points d'une référence de membre (::)
  • Un nom de méthode ou de constructeur reste attaché à la parenthèse ouvrante (() qui le suit
  • Une virgule (,) reste attachée au jeton qui la précède
  • Une flèche lambda (->) reste attachée à la liste d'arguments qui la précède

Fonctions

Lorsqu'une signature de fonction ne tient pas sur une seule ligne, passez à la ligne pour chaque déclaration de paramètre. Les paramètres définis dans ce format doivent utiliser un seul retrait (+4). La parenthèse fermante ()) et le type renvoyé sont placés sur leur propre ligne sans retrait supplémentaire.

fun <T> Iterable<T>.joinToString(
    separator: CharSequence = ", ",
    prefix: CharSequence = "",
    postfix: CharSequence = ""
): String {
    // …
}
Fonctions d'expression

Lorsqu'une fonction ne contient qu'une seule expression, elle peut être représentée par une fonction d'expression.

override fun toString(): String {
    return "Hey"
}
override fun toString(): String = "Hey"

Propriétés

Lorsqu'un initialiseur de propriété ne tient pas sur une seule ligne, passez à la ligne après le signe égal (=) et utilisez un retrait.

private val defaultCharset: Charset? =
    EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)

Les propriétés déclarant une fonction get et/ou set doivent les placer chacune sur une nouvelle ligne avec un retrait normal (+4). Appliquez les mêmes règles de mise en page que pour les fonctions.

var directory: File? = null
    set(value) {
        // …
    }
Les propriétés en lecture seule peuvent utiliser une syntaxe plus courte qui tient sur une seule ligne.
val defaultExtension: String get() = "kt"

Espace blanc

Vertical

Ajoutez une seule ligne vide :

  • Entre plusieurs membres consécutifs d'une classe : propriétés, constructeurs, fonctions, classes imbriquées, etc.
    • Exception : Il est facultatif d'ajouter une ligne vide entre deux propriétés consécutives (sans autre code entre elles). Ces lignes vides sont utilisées si nécessaire pour créer des regroupements logiques de propriétés et associer, le cas échéant, des propriétés à leur propriété de support.
    • Exception : Les lignes vides entre les constantes d'énumération sont abordées ci-dessous.
  • Entre les instructions si nécessaire pour organiser le code en sous-sections logiques.
  • Facultatif (ni conseillé, ni déconseillé) : Avant la première instruction d'une fonction, et avant le premier membre d'une classe ou après le dernier.
  • Comme indiqué dans d'autres sections de ce document (telles que la section Structure).

Vous pouvez utiliser plusieurs lignes vides consécutives, mais elles ne sont pas nécessaires ni conseillées.

Horizontal

Outre les cas où le langage ou d'autres règles de style l'exigent, et à l'exception des littéraux, des commentaires et des KDoc, un seul espace ASCII est ajouté uniquement aux emplacements suivants :

  • Lors de la séparation d'un mot réservé, tel que if, for ou catch et d'une parenthèse ouvrante (() qui le suit sur la même ligne.
    // WRONG!
    for(i in 0..1) {
    }
    
    // Okay
    for (i in 0..1) {
    }
    
  • Lors de la séparation d'un mot réservé, tel que else ou catch et d'une accolade fermante (}) qui le précède sur la même ligne.
    // WRONG!
    }else {
    }
    
    // Okay
    } else {
    }
    
  • Avant toute accolade ouvrante ({).
    // WRONG!
    if (list.isEmpty()){
    }
    
    // Okay
    if (list.isEmpty()) {
    }
    
  • Des deux côtés d'un opérateur binaire.
    // WRONG!
    val two = 1+1
    
    // Okay
    val two = 1 + 1
    
    Cette règle s'applique également aux symboles de type opérateur suivants :
    • Flèche dans une expression lambda (->).
      // WRONG!
      ints.map { value->value.toString() }
      
      // Okay
      ints.map { value -> value.toString() }
      
    Elle ne s'applique pas aux éléments suivants :
    • Le double deux-points (::) d'une référence de membre
      // WRONG!
      val toString = Any :: toString
      
      // Okay
      val toString = Any::toString
      
    • Le point de séparation (.)
      // WRONG
      it . toString()
      
      // Okay
      it.toString()
      
    • L'opérateur de plage (..)
      // WRONG
       for (i in 1 .. 4) print(i)
       
       // Okay
       for (i in 1..4) print(i)
      
  • Avant le deux-points (:) uniquement s'il est utilisé dans une déclaration de classe pour spécifier une classe de base ou des interfaces, ou s'il est utilisé dans une clause where pour une contrainte générique.
    // WRONG!
    class Foo: Runnable
    
    // Okay
    class Foo : Runnable
    
    // WRONG
    fun <T: Comparable> max(a: T, b: T)
    
    // Okay
    fun <T : Comparable> max(a: T, b: T)
    
    // WRONG
    fun <T> max(a: T, b: T) where T: Comparable<T>
    
    // Okay
    fun <T> max(a: T, b: T) where T : Comparable<T>
    
  • Après une virgule (,) ou un deux-points (:)
    // WRONG!
    val oneAndTwo = listOf(1,2)
    
    // Okay
    val oneAndTwo = listOf(1, 2)
    
    // WRONG!
    class Foo :Runnable
    
    // Okay
    class Foo : Runnable
    
  • Des deux côtés de la double barre oblique (//) qui commence un commentaire de fin de ligne. Dans ce cas, plusieurs espaces sont autorisés, mais pas obligatoires.
    // WRONG!
    var debugging = false//disabled by default
    
    // Okay
    var debugging = false // disabled by default
    

Cette règle n'est jamais interprétée comme nécessitant ou interdisant l'ajout d'un espace au début ou à la fin d'une ligne. Elle ne concerne que l'espace intérieur.

Constructions spécifiques

Classes d'énumération

Une énumération sans fonction ni documentation sur ses constantes peut éventuellement être mise en forme sur une seule ligne.

enum class Answer { YES, NO, MAYBE }

Lorsque les constantes d'une énumération sont placées sur des lignes distinctes, aucune ligne vide n'est requise entre elles, sauf si elles définissent un corps.

enum class Answer {
    YES,
    NO,

    MAYBE {
        override fun toString() = """¯\_(ツ)_/¯"""
    }
}

Étant donné que les énumérations sont des classes, toutes les autres règles de mise en forme qui s'appliquent aux classes s'y appliquent également.

Annotations

Les annotations de type ou de membre sont placées sur des lignes distinctes juste avant la construction annotée.

@Retention(SOURCE)
@Target(FUNCTION, PROPERTY_SETTER, FIELD)
annotation class Global

Les annotations sans argument peuvent être placées sur une seule ligne.

@JvmField @Volatile
var disposable: Disposable? = null

Lorsqu'une seule annotation sans argument est présente, elle peut être placée sur la même ligne que la déclaration.

@Volatile var disposable: Disposable? = null

@Test fun selectAll() {
    // …
}

La syntaxe @[...] ne peut être utilisée qu'avec une cible explicite d'utilisation du site, et uniquement pour combiner au moins deux annotations sans argument sur une seule ligne.

@field:[JvmStatic Volatile]
var disposable: Disposable? = null

Types renvoyés/Types de propriétés implicites

Si le corps d'une fonction d'expression ou un initialiseur de propriété est une valeur scalaire ou si le type renvoyé peut être clairement déduit du corps, il peut être omis.

override fun toString(): String = "Hey"
// becomes
override fun toString() = "Hey"
private val ICON: Icon = IconLoader.getIcon("/icons/kotlin.png")
// becomes
private val ICON = IconLoader.getIcon("/icons/kotlin.png")

Lorsque vous écrivez une bibliothèque, conservez la déclaration de type explicite si elle fait partie de l'API publique.

Dénominations

Les identifiants n'utilisent que des lettres et des chiffres ASCII, ainsi que des traits de soulignement dans un petit nombre de cas, indiqués ci-dessous. Ainsi, chaque nom d'identifiant valide correspond à l'expression régulière \w+.

Les préfixes ou suffixes spéciaux, comme ceux des exemples name_, mName, s_name et kName, ne sont utilisés que dans les propriétés de support (voir Propriétés de support).

Noms des packages

Les noms de packages s'écrivent en minuscules et sont simplement concaténés (sans traits de soulignement).

// Okay
package com.example.deepspace
// WRONG!
package com.example.deepSpace
// WRONG!
package com.example.deep_space

Noms des types

Les noms de classes sont en PascalCase et représentent en général des noms ou des syntagmes nominaux. Exemples : Character ou ImmutableList. Les noms d'interface peuvent également être des noms ou des syntagmes nominaux (par exemple, List). Parfois, il peut également s'agir d'adjectifs ou de syntagmes adjectivaux (par exemple, Readable).

Les classes de test portent un nom qui commence par le nom de la classe qu'elles testent et se termine par Test. Exemples : HashTest ou HashIntegrationTest.

Noms des fonctions

Les noms de fonctions sont écrits en camelCase et représentent en général des verbes ou des syntagmes verbaux. Exemples : sendMessage ou stop.

Des traits de soulignement peuvent être ajoutés dans les noms de fonctions de test pour séparer leurs composants logiques.

@Test fun pop_emptyStack() {
    // …
}

Les fonctions annotées avec @Composable qui renvoient Unit sont en PascalCase et désignés par des noms, comme s'il s'agissait de types.

@Composable
fun NameTag(name: String) {
    // …
}

Les noms de fonctions ne doivent pas contenir d'espaces, car elles ne sont pas compatibles avec toutes les plates-formes (en particulier, elles ne sont pas entièrement compatibles avec Android).

// WRONG!
fun `test every possible case`() {}
// OK
fun testEveryPossibleCase() {}

Noms des constantes

Les noms de constantes sont en UPPER_SNAKE_CASE, c'est-à-dire en lettres majuscules avec des mots séparés par des traits de soulignement. Qu'est-ce qu'une constante ?

Une constante est une propriété val sans fonction get personnalisée, dont le contenu est immuable et dont les fonctions n'ont aucun effet secondaire détectable. Cela inclut les types immuables et les collections immuables de types immuables, ainsi que les valeurs scalaires et les chaînes si elles sont marquées comme const. Si l'un des états observables d'une instance peut changer, il ne s'agit pas d'une constante. La seule intention de ne jamais faire muter l'objet ne suffit pas.

const val NUMBER = 5
val NAMES = listOf("Alice", "Bob")
val AGES = mapOf("Alice" to 35, "Bob" to 32)
val COMMA_JOINER = Joiner.on(',') // Joiner is immutable
val EMPTY_ARRAY = arrayOf()

Ces noms représentent en général des noms ou des syntagmes nominaux.

Les valeurs de constante ne peuvent être définies que dans un object ou en tant que déclaration de niveau supérieur. Les valeurs qui répondent à l'exigence d'une constante, mais qui sont définies à l'intérieur d'une class doivent utiliser un nom non constant.

Les constantes qui sont des valeurs scalaires doivent utiliser le modificateur const.

Noms non constants

Les noms non constants sont écrits en camelCase. Cela s'applique aux propriétés d'instance, aux propriétés locales et aux noms de paramètres.

val variable = "var"
val nonConstScalar = "non-const"
val mutableCollection: MutableSet = HashSet()
val mutableElements = listOf(mutableInstance)
val mutableValues = mapOf("Alice" to mutableInstance, "Bob" to mutableInstance2)
val logger = Logger.getLogger(MyClass::class.java.name)
val nonEmptyArray = arrayOf("these", "can", "change")

Ces noms représentent en général des noms ou des syntagmes nominaux.

Propriétés de support

Lorsqu'une propriété de support est nécessaire, son nom doit correspondre exactement à celui de la propriété réelle, à l'exception d'un trait de soulignement en préfixe.

private var _table: Map? = null

val table: Map
    get() {
        if (_table == null) {
            _table = HashMap()
        }
        return _table ?: throw AssertionError()
    }

Noms des variables de type

Chaque variable de type est nommée dans l'un des deux styles suivants :

  • Une seule lettre majuscule, suivie éventuellement d'un seul chiffre (par exemple, E, T, X, T2)
  • Un nom au format utilisé pour les classes, suivi de la lettre majuscule T (par exemple, RequestT ou FooBarT)

Camel case

Parfois, iI existe plusieurs façons de convertir une expression anglaise en camelCase, par exemple en présence d'acronymes ou de constructions inhabituelles comme "IPv6" ou "iOS". Pour améliorer la prévisibilité, utilisez le schéma suivant.

En commençant par la forme en prose du nom :

  1. Convertissez l'expression en ASCII simple et supprimez toutes les apostrophes. Ainsi, "Müller’s algorithm" devient "Muellers algorithm".
  2. Divisez le résultat en plusieurs mots, séparés par des espaces et par les signes de ponctuation restants (généralement des traits d'union). Recommandé : Si l'un des mots présente déjà une apparence conventionnelle, vous pouvez le diviser en différentes parties (par exemple, "AdWords" devient "ad words").Notez qu'un terme comme "iOS" n'est pas réellement en camelCase. Il défie toute convention, cette recommandation ne s'applique donc pas.
  3. Mettez tout en minuscules (y compris les acronymes), puis effectuez l'une des opérations suivantes :
    • Mettez en majuscule le premier caractère de chaque mot pour obtenir le PascalCase.
    • Mettez en majuscule le premier caractère de chaque mot, à l'exception du premier mot pour obtenir le PascalCase.
  4. Regroupez tous les mots en un seul identifiant.

Notez que la casse d'origine est presque entièrement ignorée.

Forme en prose Correct Incorrect
"XML Http Request" XmlHttpRequest XMLHTTPRequest
"new customer ID" newCustomerId newCustomerID
"inner stopwatch" innerStopwatch innerStopWatch
"supports IPv6 on iOS" supportsIpv6OnIos supportsIPv6OnIOS
"YouTube importer" YouTubeImporter YoutubeImporter*

(* Acceptable, mais pas recommandé.)

Documentation

Mise en forme

Voici un exemple de mise en forme de base des blocs KDoc :

/**
 * Multiple lines of KDoc text are written here,
 * wrapped normally…
 */
fun method(arg: String) {
    // …
}

En voici un autre, sur une seule ligne :

/** An especially short bit of KDoc. */

Le format de base est toujours acceptable. La forme à une ligne peut être utilisée lorsque l'intégralité du bloc KDoc (y compris les marqueurs de commentaires) peut tenir sur une seule ligne. Notez que cela ne s'applique que lorsqu'il n'existe aucune balise de bloc comme @return.

Paragraphes

Une ligne vide, c'est-à-dire ne contenant que l'astérisque de début aligné (*), est ajoutée entre les paragraphes et, le cas échéant, avant le groupe de balises de bloc.

Balises de bloc

Toutes les balises de bloc standards utilisées apparaissent dans l'ordre @constructor, @receiver, @param, @property, @return, @throws et @see. Elles n'apparaissent jamais avec une description vide. Lorsqu'une balise de bloc ne tient pas sur une seule ligne, les lignes de continuation sont mises en retrait de quatre espaces par rapport à la position du @.

Fragment récapitulatif

Chaque bloc KDoc commence par un bref fragment récapitulatif. Ce fragment est très important : c'est la seule partie du texte qui apparaît dans certains contextes, tels que les index de méthode et de classe.

Il s'agit d'un fragment (un syntagme nominal ou verbal), pas d'une phrase complète. Un fragment récapitulatif ne commence pas par "A `Foo` is a..." ou "This method returns...", et ne doit pas nécessairement former une phrase impérative complète comme "Save the record.". Cependant, il respecte les majuscules et la ponctuation comme s'il s'agissait d'une phrase complète.

Utilisation

Au minimum, KDoc est présent pour chaque type public et chaque membre public ou protected de ce type, à quelques exceptions près, comme indiqué ci-dessous.

Exception : fonctions explicites

KDoc est facultatif pour les fonctions simples et évidentes comme getFoo et les propriétés comme foo, quand il n'y a rien d'autre à dire à part "Returns the foo" (Renvoie le foo).

Il n'est pas approprié de citer cette exception pour justifier l'omission d'informations pertinentes qu'un lecteur type aurait besoin de connaître. Ainsi, pour une fonction nommée getCanonicalName ou une propriété nommée canonicalName, n'omettez pas sa documentation (au motif qu'elle ne dirait que /** Returns the canonical name. */) si le lecteur type ne sait pas ce que signifie le terme "canonical name".

Exception : remplacements

KDoc n'est pas toujours présent dans une méthode qui remplace une méthode de supertype.