Guida di stile Kotlin

Questo documento rappresenta la definizione completa degli standard di codifica Android di Google per il codice sorgente nel linguaggio di programmazione Kotlin. Un file sorgente Kotlin viene descritto come in Google Android Style solo se rispetta le regole quivi.

Come altre guide di stile di programmazione, i problemi trattati non riguardano solo questioni estetiche di formattazione, ma anche altri tipi di convenzioni o standard di programmazione. Tuttavia, il presente documento si concentra principalmente sulle regole ferree che seguiamo universalmente e non fornisce consigli che non sono chiaramente applicabili (per persona o per mezzo di strumenti).

Ultimo aggiornamento: 06-09-2023

File di origine

Tutti i file di origine devono essere codificati con la codifica UTF-8.

Denominazione

Se un file di origine contiene una sola classe di primo livello, il nome del file deve riflettere il nome che fa distinzione tra maiuscole e minuscole più l'estensione .kt. Altrimenti, se un file di origine contiene più dichiarazioni di primo livello, scegli un nome che ne descriva i contenuti, applica PascalCase (camelCase è accettabile se il nome del file è plurale) e aggiungi l'estensione .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> = // …
// extensions.kt
fun MyClass.process() = // …
fun MyResult.print() = // …

Caratteri speciali

Caratteri con spazio vuoto

A parte la sequenza di terminazione di riga, lo spazio orizzontale ASCII (0x20) è l'unico spazio vuoto che compare in qualsiasi punto di un file di origine. Ciò implica che:

  • Tutti gli altri spazi nei valori letterali stringa e carattere vengono sottoposti a escape.
  • I caratteri di tabulazione non vengono utilizzati per il rientro.

Sequenze di escape speciali

Per ogni carattere con una sequenza di escape speciale (\b, \n, \r, \t, \', \", \\ e \$), viene utilizzata questa sequenza anziché il corrispondente Unicode (ad es. \u000a).

Caratteri non ASCII

Per i caratteri non ASCII rimanenti, il carattere Unicode effettivo (ad es. ) o l'escape Unicode equivalente (ad es. \u221e). La scelta dipende solo da ciò che rende il codice più facile da leggere e capire. L'utilizzo di escape Unicode è sconsigliato per i caratteri stampabili in qualsiasi luogo ed è fortemente sconsigliato al di fuori dei valori letterali stringa e dei commenti.

Esempio Discussione
val unitAbbrev = "μs" Migliore: nitidezza perfetta anche senza commento.
val unitAbbrev = "\u03bcs" // μs Scarsa: non c'è motivo di utilizzare un carattere di escape con un carattere stampabile.
val unitAbbrev = "\u03bcs" Scarsa: il lettore non ha idea di cosa sia.
return "\ufeff" + content Soluzione ottimale: utilizza la sequenza di escape per i caratteri non stampabili e, se necessario, commenta.

Struttura

Un file .kt comprende quanto segue, nell'ordine:

  • Intestazione relativa a copyright e/o licenza (facoltativo)
  • Annotazioni a livello di file
  • Istruzione pacchetto
  • Importa istruzioni
  • Dichiarazioni di primo livello

Ciascuna di queste sezioni è separata da una riga vuota.

Se un'intestazione relativa a copyright o licenza appartiene al file, deve essere inserita all'inizio di un commento su più righe.

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

Non utilizzare un commento in stile KDoc o in una riga singola.

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

Annotazioni a livello di file

Le annotazioni con il nome use-site target "file" vengono inserite tra qualsiasi commento dell'intestazione e la dichiarazione del pacchetto.

Istruzione pacchetto

L'istruzione del pacchetto non è soggetta ad alcun limite di colonne e non viene mai aggregata a capo.

Importa istruzioni

Le istruzioni di importazione per classi, funzioni e proprietà sono raggruppate in un unico elenco e ordinate da ASCII.

Le importazioni con caratteri jolly (di qualsiasi tipo) non sono consentite.

Analogamente all'istruzione del pacchetto, le istruzioni di importazione non sono soggette a un limite di colonne e non vengono mai sottoposte a wrapping.

Dichiarazioni di primo livello

Un file .kt può dichiarare uno o più tipi, funzioni, proprietà o alias di tipo al livello superiore.

I contenuti di un file devono essere incentrati su un singolo tema. Esempi di ciò sono un singolo tipo pubblico o un insieme di funzioni di estensione che eseguono la stessa operazione su più tipi di ricevitori. Le dichiarazioni non correlate devono essere separate nei propri file e le dichiarazioni pubbliche all'interno di un singolo file devono essere ridotte a icona.

Non vengono applicate restrizioni esplicite al numero o all'ordine dei contenuti di un file.

I file di origine in genere vengono letti dall'alto verso il basso, il che significa che l'ordine, in generale, dovrebbe riflettere che le dichiarazioni più in alto saranno utili per la comprensione di quelle più in basso. File diversi possono scegliere di ordinare i contenuti in modo diverso. Analogamente, un file può contenere 100 proprietà, altre 10 funzioni e un'altra ancora, una singola classe.

È importante che ogni file utilizzi un po' di ordine logico, che il gestore potrebbe spiegare se richiesto. Ad esempio, le nuove funzioni non vengono solo aggiunte abitualmente alla fine del file, in quanto produrrebbe l'ordinamento "cronologico per data di aggiunta", che non è un ordine logico.

Ordinare membri del corso

L'ordine dei membri all'interno di una classe segue le stesse regole delle dichiarazioni di livello superiore.

Formattazione

Apparecchi ortodontici

Le parentesi graffe non sono necessarie per i rami when e le espressioni if che non hanno più di un ramo else e che rientrano in una singola riga.

if (string.isEmpty()) return

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

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

Le parentesi graffe sono altrimenti obbligatorie per qualsiasi ramo if, for, when, do e while, anche se il corpo è vuoto o contiene una sola istruzione.

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)
}

Blocchi non vuoti

Le parentesi graffe seguono lo stile Kernighan e Ritchie ("parentesi egizie") per blocchi non vuoti e costrutti tipo blocco:

  • Nessuna interruzione di riga prima della parentesi graffa di apertura.
  • Interruzione di riga dopo la parentesi graffa di apertura.
  • Interruzione di riga prima della parentesi graffa di chiusura.
  • Interruzione di riga dopo la parentesi graffa di chiusura, solo se termina un'istruzione o termina il corpo di una funzione, un costruttore o una classe named. Ad esempio, non c'è un'interruzione di riga dopo la parentesi graffa se è seguita da else o da una virgola.
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()
        }
    }
}

Di seguito sono riportate alcune eccezioni per le classi di enum.

Blocchi vuoti

Un blocco vuoto o un costrutto di tipo blocco deve essere in stile K&R.

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

Espressioni

Una condizione if/else utilizzata come espressione può omettere le parentesi graffe solo se l'intera espressione rientra su una sola riga.

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
}

Rientro

Ogni volta che viene aperto un nuovo blocco o struttura di tipo blocco, il rientro aumenta di quattro spazi. Al termine del blocco, il rientro torna al livello precedente. Il livello di rientro si applica sia al codice sia ai commenti all'interno del blocco.

Un'istruzione per riga

Ogni istruzione è seguita da un'interruzione di riga. I punti e virgola non vengono utilizzati.

Ritorno a capo automatico

Il codice ha un limite di colonne di 100 caratteri. Ad eccezione di quanto indicato di seguito, qualsiasi riga che supererebbe questo limite deve essere sottoposta a wrapping, come illustrato di seguito.

Eccezioni:

  • Righe in cui non è possibile rispettare il limite di colonne (ad esempio, un URL lungo in KDoc)
  • Istruzioni package e import
  • Righe di comando in un commento che possono essere tagliate e incollate in una shell

Dove interrompere

La principale direttiva del wrapping di righe è la preferenza di interruzione a un livello sintattico più elevato. Inoltre:

  • Quando una riga viene interrotta in corrispondenza di un operatore o del nome di funzione infisso, l'interruzione segue il nome dell'operatore o della funzione infisso.
  • Quando una linea è interrotta in corrispondenza dei seguenti simboli "simili a un operatore", l'interruzione precede il simbolo:
    • Il separatore di punto (., ?.).
    • I due due punti del riferimento a un membro (::).
  • Il nome di un metodo o di un costruttore rimane collegato alla parentesi aperta (() che lo segue.
  • Una virgola (,) rimane collegata al token che la precede.
  • Una freccia lambda (->) rimane collegata all'elenco di argomenti che la precede.

Funzioni

Quando la firma di una funzione non rientra su una sola riga, suddividi ogni dichiarazione di parametro sulla rispettiva riga. I parametri definiti in questo formato devono utilizzare un singolo rientro (+4). La parentesi di chiusura ()) e il tipo restituito vengono inseriti su una riga separata senza alcun rientro aggiuntivo.

fun <T> Iterable<T>.joinToString(
    separator: CharSequence = ", ",
    prefix: CharSequence = "",
    postfix: CharSequence = ""
): String {
    // …
}
Funzioni di espressione

Quando una funzione contiene una sola espressione, può essere rappresentata come una funzione di espressione.

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

Proprietà

Quando un inizializzatore di proprietà non rientra in una singola riga, interrompi dopo il segno di uguale (=) e utilizza un rientro.

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

Le proprietà che dichiarano una funzione get e/o set devono posizionarle ciascuna sulla rispettiva riga con un rientro normale (+4). Formattale utilizzando le stesse regole delle funzioni.

var directory: File? = null
    set(value) {
        // …
    }
Le proprietà di sola lettura possono utilizzare una sintassi più breve che può essere contenuta in una singola riga.
val defaultExtension: String get() = "kt"

Spazio vuoto

Verticale

Viene visualizzata una singola riga vuota:

  • Tra membri consecutivi di una classe: proprietà, costruttori, funzioni, classi nidificate e così via.
    • Eccezione: una riga vuota tra due proprietà consecutive (senza altri codici) è facoltativa. Queste righe vuote vengono utilizzate secondo necessità per creare raggruppamenti logici di proprietà e associare proprietà alla relativa proprietà di supporto, se presente.
    • Eccezione: le righe vuote tra le costanti enum sono coperte di seguito.
  • Tra istruzioni, se necessario per organizzare il codice in sottosezioni logiche.
  • Facoltativamente, prima della prima istruzione di una funzione, prima del primo membro di una classe o dopo l'ultimo membro di una classe (né incoraggiato né sconsigliato).
  • Come richiesto da altre sezioni del presente documento (ad esempio la sezione Struttura).

Sono consentite più righe vuote consecutive, ma non sono consigliate o mai obbligatorie.

Orizzontale

Oltre a dove richiesto dal linguaggio o da altre regole di stile, e ad eccezione di valori letterali, commenti e KDoc, un singolo spazio ASCII viene visualizzato solo nelle seguenti posizioni:

  • Separando qualsiasi parola riservata, come if, for o catch, dalla parentesi aperta (() che la segue sulla riga in questione.
    // WRONG!
    for(i in 0..1) {
    }
    
    // Okay
    for (i in 0..1) {
    }
    
  • Separare qualsiasi parola riservata, come else o catch, da una parentesi graffa di chiusura (}) che la precede sulla riga in questione.
    // WRONG!
    }else {
    }
    
    // Okay
    } else {
    }
    
  • Prima di qualsiasi parentesi graffa aperta ({).
    // WRONG!
    if (list.isEmpty()){
    }
    
    // Okay
    if (list.isEmpty()) {
    }
    
  • Su entrambi i lati di qualsiasi operatore binario.
    // WRONG!
    val two = 1+1
    
    // Okay
    val two = 1 + 1
    
    Questo vale anche per i seguenti simboli "simili a un operatore":
    • la freccia in un'espressione lambda (->).
      // WRONG!
      ints.map { value->value.toString() }
      
      // Okay
      ints.map { value -> value.toString() }
      
    Ma non è così:
    • i due due punti (::) di un riferimento membro.
      // WRONG!
      val toString = Any :: toString
      
      // Okay
      val toString = Any::toString
      
    • il separatore di punto (.).
      // WRONG
      it . toString()
      
      // Okay
      it.toString()
      
    • l'operatore di intervallo (..).
      // WRONG
      for (i in 1 .. 4) {
        print(i)
      }
      
      // Okay
      for (i in 1..4) {
        print(i)
      }
      
  • Prima dei due punti (:) solo se utilizzato in una dichiarazione di classe per specificare una o più interfacce di base oppure quando utilizzato in una clausola where per i vincoli generici.
    // 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>
    
  • Dopo la virgola (,) o i due punti (:).
    // WRONG!
    val oneAndTwo = listOf(1,2)
    
    // Okay
    val oneAndTwo = listOf(1, 2)
    
    // WRONG!
    class Foo :Runnable
    
    // Okay
    class Foo : Runnable
    
  • Su entrambi i lati della doppia barra (//) che inizia un commento alla fine della riga. In questo caso, sono consentiti, ma non obbligatori.
    // WRONG!
    var debugging = false//disabled by default
    
    // Okay
    var debugging = false // disabled by default
    

Questa regola non viene mai interpretata come la richiesta o la proibizione di spazio aggiuntivo all'inizio o alla fine di una linea; si occupa solo dello spazio interno.

Costrutti specifici

Classi di enumerazione

Un'enum senza funzione e senza documentazione sulle sue costanti può facoltativamente essere formattata su una riga singola.

enum class Answer { YES, NO, MAYBE }

Quando le costanti di un'enum vengono inserite su righe separate, non è necessaria una riga vuota tra di loro, tranne nel caso in cui definiscano un corpo.

enum class Answer {
    YES,
    NO,

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

Poiché le classi di enum sono classi, si applicano tutte le altre regole per le classi di formattazione.

Annotazioni

Le annotazioni di tipo o membro vengono posizionate su righe separate immediatamente prima del costrutto annotato.

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

Le annotazioni senza argomenti possono essere inserite su una singola riga.

@JvmField @Volatile
var disposable: Disposable? = null

Quando è presente una sola annotazione senza argomenti, può essere posizionata sulla stessa riga della dichiarazione.

@Volatile var disposable: Disposable? = null

@Test fun selectAll() {
    // …
}

La sintassi @[...] può essere utilizzata solo con una destinazione esplicita del sito di utilizzo e solo per combinare due o più annotazioni senza argomenti su una singola riga.

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

Resi/tipi di proprietà impliciti

Se il corpo di una funzione di espressione o un inizializzatore di proprietà è un valore scalare o il tipo restituito può essere dedotto chiaramente dal corpo, può essere omesso.

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")

Quando scrivi una libreria, conserva la dichiarazione esplicita del tipo se fa parte dell'API pubblica.

Denominazione

Gli identificatori utilizzano solo lettere e numeri ASCII e, in un numero limitato di casi indicati di seguito, trattini bassi. In questo modo, ogni nome identificatore valido corrisponde all'espressione regolare \w+.

Prefissi o suffissi speciali, come quelli presenti negli esempi name_, mName, s_name e kName, non vengono utilizzati se non nel caso delle proprietà di supporto (consulta la sezione Proprietà di supporto).

Nomi dei pacchetti

I nomi dei pacchetti sono tutti minuscoli, con parole consecutive semplicemente concatenate (senza trattini bassi).

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

Digita nomi

I nomi delle classi sono scritti in PascalCase e sono generalmente sostantivi o frasi sostantive. Ad esempio, Character o ImmutableList. I nomi delle interfacce possono anche essere sostantivi o frasi sostantive (ad esempio, List), ma a volte potrebbero essere invece aggettivi o frasi aggettive (ad esempio Readable).

I nomi delle classi di test iniziano con il nome della classe che stanno testando e terminano con Test. Ad esempio, HashTest o HashIntegrationTest.

Nomi delle funzioni

I nomi delle funzioni sono scritti in camelCase e sono generalmente verbi o frasi verbali. Ad esempio, sendMessage o stop.

I trattini bassi possono apparire nei nomi delle funzioni di test per separare i componenti logici del nome.

@Test fun pop_emptyStack() {
    // …
}

Le funzioni annotate con @Composable che restituiscono Unit sono PascalCased e denominate come sostantivi, come se fossero tipi.

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

I nomi delle funzioni non devono contenere spazi perché non sono supportati su tutte le piattaforme (in particolare, non sono completamente supportati in Android).

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

Nomi costanti

I nomi di costanti usano UPPER_SNAKE_CASE: tutte lettere maiuscole, con le parole separate da trattini bassi. Ma che cos'è esattamente una costante?

Le costanti sono proprietà val senza funzione get personalizzata, i cui contenuti sono profondamente immutabili e le cui funzioni non hanno effetti collaterali rilevabili. Ciò include tipi immutabili e raccolte immutabili di tipi immutabili, nonché scalari e stringhe se contrassegnate come const. Se uno qualsiasi degli stati osservabili di un'istanza può cambiare, non si tratta di una costante. Limitarsi a non mutare mai l'oggetto non è sufficiente.

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()

Questi nomi sono in genere sostantivi o frasi sostantive.

I valori costanti possono essere definiti solo all'interno di un elemento object o come una dichiarazione di primo livello. I valori che soddisfano il requisito di una costante ma definiti all'interno di un class devono utilizzare un nome non costante.

Le costanti che sono valori scalari devono utilizzare il modificatore const.

Nomi non costanti

I nomi non costanti sono scritti in camelCase. Queste norme si applicano alle proprietà dell'istanza, alle proprietà locali e ai nomi dei parametri.

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")

Questi nomi sono in genere sostantivi o frasi sostantive.

Proprietà di supporto

Quando è necessaria una proprietà di supporto, il nome deve corrispondere esattamente a quello della proprietà reale, tranne se è preceduto da un trattino basso.

private var _table: Map? = null

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

Digita i nomi delle variabili

Ogni variabile di tipo viene denominata in uno dei due stili seguenti:

  • Una singola lettera maiuscola, facoltativamente seguita da un singolo numero (ad esempio E, T, X, T2)
  • Un nome nel formato utilizzato per i corsi, seguito dalla lettera maiuscola T (ad esempio RequestT, FooBarT)

Custodia a cammello

A volte c'è più di un modo ragionevole per convertire una frase inglese in cagnolino, ad esempio quando sono presenti acronimi o costrutti insoliti come "IPv6" o "iOS". Per migliorare la prevedibilità, utilizza lo schema seguente.

Inizia con la prosa del nome:

  1. Converti la frase in ASCII semplice e rimuovi tutti gli apostrofi. Ad esempio, "Algoritmo di Müller" potrebbe diventare "Algoritmo di Muellers".
  2. Dividi questo risultato in parole, separandole in spazi ed eventuali segni di punteggiatura rimanenti (in genere trattini). Consigliato: se una parola ha già un uso comune nell'uso di una cassa a cammello, suddividila nelle sue parti costitutive (ad es. "AdWords" diventa "parole annuncio"). Tieni presente che una parola come "iOS" non è una parola usata per le parole in cammello di per sé e viola qualsiasi convenzione, per cui questo consiglio non si applica.
  3. Ora inserisci in minuscolo tutto (compresi gli acronimi), quindi esegui una delle seguenti operazioni:
    • Utilizza il maiuscolo per il primo carattere di ogni parola per ottenere il carattere pascal.
    • Scrivi in maiuscolo il primo carattere di ogni parola, tranne il primo per indicare la maiuscola a cammello.
  4. Infine, unisci tutte le parole in un unico identificatore.

Tieni presente che l'uso delle maiuscole/minuscole delle parole originali viene quasi completamente ignorato.

Formato in prosa Corretto Risposta sbagliata
"Richiesta HTTP XML" XmlHttpRequest XMLHTTPRequest
"nuovo ID cliente" newCustomerId newCustomerID
"cronometro interno" innerStopwatch innerStopWatch
"supporta IPv6 su iOS" supportsIpv6OnIos supportsIPv6OnIOS
"Importatore YouTube" YouTubeImporter YoutubeImporter*

(* Accettabile, ma non consigliato).

Documentazione

Formattazione

La formattazione di base dei blocchi KDoc è mostrata in questo esempio:

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

...o in questo esempio a riga singola:

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

Il formato di base è sempre accettabile. Il modulo a una riga può essere sostituito quando l'intero blocco di KDoc (inclusi gli indicatori di commento) può essere inserito su una singola riga. Tieni presente che questo vale solo quando non sono presenti tag di blocco come @return.

Paragrafi

Tra i paragrafi e prima del gruppo di tag di blocco, se presente, viene visualizzata una riga vuota, ovvero una riga contenente solo l'asterisco iniziale allineato (*).

Blocca tag

Tutti i "tag di blocco" standard utilizzati vengono visualizzati nell'ordine @constructor, @receiver, @param, @property, @return, @throws, @see e questi non vengono mai visualizzati con una descrizione vuota. Quando un tag blocco non rientra su una singola riga, le righe di continuazione vengono rientrate di 4 spazi rispetto alla posizione dell'elemento @.

Frammento di riepilogo

Ogni blocco di KDoc inizia con un breve frammento di riepilogo. Questo frammento è molto importante: è l'unica parte del testo che appare in determinati contesti, come gli indici di classi e metodi.

Si tratta di un frammento, ovvero di una frase verbale o di una frase, non di una frase completa. Non inizia con "A `Foo` is a...", o "This method returns...", né deve formare una frase imperativa completa come "Save the record.". Tuttavia, il frammento è in maiuscolo e punteggiato come se fosse una frase completa.

Utilizzo

Come minimo, KDoc è presente per ogni tipo public e ogni membro public o protected di questo tipo, con alcune eccezioni indicate di seguito.

Eccezione: funzioni autoesplicative

KDoc è facoltativo per le funzioni "semplici ed evidenti" come getFoo e proprietà come foo, nei casi in cui non c'è nient'altro che vale la pena dire, ma "restituisce il foo".

Non è appropriato citare questa eccezione per giustificare l'omissione di informazioni pertinenti che un lettore tipico potrebbe avere bisogno di conoscere. Ad esempio, per una funzione denominata getCanonicalName o una proprietà denominata canonicalName, non omettere la relativa documentazione (con la motivazione che direbbe solo /** Returns the canonical name. */) se un lettore tipico potrebbe non avere idea del significato del termine "nome canonico".

Eccezione: override

KDoc non è sempre presente in un metodo che sostituisce un metodo di supertipo.