Questo documento rappresenta la definizione completa degli standard di programmazione Android di Google per il codice sorgente nel linguaggio di programmazione Kotlin. Un file sorgente Kotlin viene descritto come in stile Google Android solo se ed è conforme alle relative regole.
Come altre guide di stile per la programmazione, i problemi trattati non riguardano solo i problemi estetici della formattazione, ma anche altri tipi di convenzioni o standard di codifica. Tuttavia, questo documento si concentra principalmente sulle regole ferree che seguiamo universalmente ed evita di dare consigli che non sono chiaramente applicabili (da parte di persone fisiche o da uno strumento).
Ultimo aggiornamento: 2023-09-06
File di origine
Tutti i file sorgente devono avere la codifica UTF-8.
Denominazione
Se un file sorgente contiene una sola classe di primo livello, il nome del file
deve riflettere il nome sensibile alle maiuscole e l'estensione .kt
. Altrimenti,
Se un file di origine contiene più dichiarazioni di primo livello, scegli un nome
che descrive i contenuti del file, applica PascalCase (camelCase è
accettabile se il nome 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 per lo spazio vuoto
A parte la sequenza di terminazioni di riga, Carattere di spazio orizzontale ASCII (0x20) è l'unico spazio vuoto che compare in un file di origine. Ciò implica che:
- Tutti gli altri spazi vuoti presenti nella stringa e nei valori letterali carattere sono sottoposti a escape.
- I caratteri di tabulazione non vengono utilizzati per il rientro.
Sequenze di escape speciali
Per qualsiasi carattere con una sequenza di escape speciale
(\b
, \n
, \r
, \t
, \'
, \"
, \\
e \$
),
viene utilizzata questa sequenza al posto del
(ad es. \u000a
).
Caratteri non ASCII
Per i restanti caratteri non ASCII, il carattere Unicode effettivo
(ad es. ∞
) o il carattere di escape Unicode equivalente (ad es. \u221e
).
La scelta dipende solo da cosa rende il codice
più facili da leggere e comprendere.
L'utilizzo di caratteri di escape Unicode è sconsigliato per i caratteri stampabili in qualsiasi posizione e
sono fortemente sconsigliati al di fuori dei valori letterali di stringa e dei commenti.
Esempio | Discussione |
---|---|
val unitAbbrev = "μs" |
Migliore: perfettamente chiara anche senza commento. |
val unitAbbrev = "\u03bcs" // μs |
Scadente: non c'è motivo di utilizzare un carattere di escape con un carattere stampabile. |
val unitAbbrev = "\u03bcs" |
Scadente: il lettore non ha idea di cosa sia. |
return "\ufeff" + content |
Buona: utilizza caratteri di escape per i caratteri non stampabili e, se necessario, commenta. |
Struttura
Un file .kt
comprende i seguenti elementi, in ordine:
- Intestazione per copyright e/o licenza (facoltativa)
- Annotazioni a livello di file
- Istruzione pacchetto
- Importa istruzioni
- Dichiarazioni di primo livello
Ciascuna di queste sezioni è separata da una riga vuota.
Copyright / licenza
Se l'intestazione di una licenza o di un copyright appartiene al file, deve essere posizionata nella parte superiore immediata di un commento su più righe.
/* * Copyright 2017 Google, Inc. * * ... */
Non utilizzare uno stile KDoc o un commento di una sola riga.
/** * Copyright 2017 Google, Inc. * * ... */
// Copyright 2017 Google, Inc. // // ...
Annotazioni a livello di file
Annotazioni con il "file" target sito d'uso Vengono posizionati tra qualsiasi commento dell'intestazione e la dichiarazione relativa al pacchetto.
Istruzione pacchetto
L'istruzione del pacchetto non è soggetta a limiti di colonne e non è mai aggregata a una riga.
Importa istruzioni
Le istruzioni di importazione per classi, funzioni e proprietà sono raggruppate in un unico elenco e ordinate in ASCII.
Le importazioni con caratteri jolly (di qualsiasi tipo) non sono consentite.
Analogamente all'istruzione pacchetto, le istruzioni di importazione non sono soggette a un limite di colonne e non viene mai aggregato.
Dichiarazioni di primo livello
Un file .kt
può dichiarare uno o più tipi, funzioni, proprietà o tipi
alias di primo livello.
I contenuti di un file devono essere incentrati su un singolo tema. Esempi 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 separati in file separati e dichiarazioni pubbliche all'interno di un unico file devono essere ridotti al minimo.
Non viene applicata alcuna restrizione esplicita al numero o all'ordine dei contenuti di un file.
I file di origine vengono generalmente letti dall'alto verso il basso, il che significa che l'ordine, in in generale, dovrebbe riflettere il fatto che le dichiarazioni più in alto informeranno comprendendo anche quelli più in basso. È possibile ordinare diversi file i contenuti in modo diverso. Analogamente, un file può contenere 100 proprietà, altre 10 funzioni e ancora una sola classe.
È importante che ogni file utilizzi un certo ordine logico, ovvero potrebbe spiegare se richiesto. Ad esempio, le nuove funzioni non sono abitualmente aggiunti alla fine del file, in quanto ciò produrrebbe una "cronologica" per data di aggiunta", che non è un ordinamento logico.
Ordinazione dei membri del corso
L'ordine dei membri all'interno di un corso segue le stesse regole dei membri di primo livello dichiarazioni.
Formattazione
Tutori
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 filiale if
, for
, when
, do
,
e while
, anche quando il corpo è vuoto o contiene solo
una singola 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 simili a blocchi:
- 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 una
o termina il corpo di una funzione, un costruttore o una classe named.
Ad esempio, non c'è interruzione di riga dopo la parentesi graffa se è seguita da
else
o 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() } } }
Alcune eccezioni per classi enum sono riportati di seguito.
Blocchi vuoti
Un blocco o un costrutto vuoto deve essere in stile K&R.
try { doSomething() } catch (e: Exception) {} // WRONG!
try { doSomething() } catch (e: Exception) { } // Okay
Espressioni
Un condizionale if/else
utilizzato come espressione può
ometti le parentesi graffe solo se l'intera espressione rientra in 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 costrutto simile a un 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 in tutto il blocco.
Un'istruzione per riga
Ogni istruzione è seguita da un'interruzione di riga. I punti e virgola non vengono utilizzati.
A capo automatico
Il codice ha un limite di 100 caratteri per le colonne. Fatto salvo quanto indicato di seguito, le righe che superano questo limite devono essere aggregate a capo, come spiegato di seguito.
Eccezioni:
- Righe in cui non è possibile rispettare il limite delle colonne (ad es. un URL lungo in un file KDoc)
- Estratti conto
package
eimport
- 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 per l'interruzione a un livello sintattico più elevato. Inoltre:
- Quando una linea è spezzata in corrispondenza del nome di un operatore o di una funzione infissa, l'interruzione compare dopo il nome dell'operatore o della funzione infissa.
- Quando una linea è spezzata in corrispondenza dei seguenti simboli "simili a un operatore", la interruzione
precede il simbolo:
- Il separatore del punto (
.
,?.
). - I due punti del riferimento di un membro (
::
).
- Il separatore del punto (
- Un metodo o un nome di costruttore rimane collegato alla parentesi aperta (
(
) che la seguite. - 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 in una sola riga, spezza ogni dichiarazione di parametro su una riga separata. I parametri definiti in questo formato devono utilizzare un rientro singolo (+4). Le parentesi di chiusura ()
) e il tipo restituito vengono posizionati su una propria riga senza rientro aggiuntivo.
fun <T> Iterable<T>.joinToString( separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "" ): String { // … }
Funzioni di espressione
Quando una funzione contiene solo una singola espressione, può essere rappresentata come 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, inserisci un'interruzione 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
alla propria riga con un rientro normale (+4). Formattale utilizzando le stesse regole
come funzioni.
var directory: File? = null set(value) { // … }
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 tra loro) è facoltativo. Queste righe vuote vengono utilizzate all'occorrenza per creare raggruppamenti logici di proprietà e proprietà associate con la relativa proprietà di supporto, se presente.
- Eccezione: vengono coperte le righe vuote tra le costanti enum. di seguito.
- Tra le istruzioni, se necessario per organizzare il codice in sottosezioni logiche.
- Facoltativamente prima della prima istruzione in una funzione, prima del primo membro di una classe o dopo l'ultimo membro di una (né incoraggiati né scoraggiati).
- Come richiesto da altre sezioni del presente documento (come il Struttura).
Più righe vuote consecutive sono consentite, ma non consigliate o mai richiesto.
Orizzontale
Oltre a dove richiesto dalla lingua o da altre regole di stile, e, a parte i valori letterali, i commenti e i documenti KDoc, un'unica e viene visualizzato solo nelle seguenti posizioni:
- Separazione di qualsiasi parola riservata, ad esempio
if
,for
, oppurecatch
da una parentesi aperta ((
) che la segue su quella riga.// WRONG! for(i in 0..1) { }
// Okay for (i in 0..1) { }
- Separazione di qualsiasi parola riservata, ad esempio
else
ocatch
, da un parentesi graffa chiusa (}
) che la precede su tale riga.// 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
Questo vale anche per i seguenti simboli "simili a un operatore":// Okay val two = 1 + 1
- la freccia in un'espressione lambda (
->
).// WRONG! ints.map { value->value.toString() }
// Okay ints.map { value -> value.toString() }
-
i due due punti (
::
) di un riferimento di membro.// WRONG! val toString = Any :: toString
// Okay val toString = Any::toString
-
il separatore del 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) }
- la freccia in un'espressione lambda (
-
Prima dei due punti (
:
) solo se utilizzati in una dichiarazione di classe per specificare una o più interfacce di base oppure quando utilizzate in una clausolawhere
della . 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 una virgola (
,
) o 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 più spazi, ma non sono obbligatori.// WRONG! var debugging = false//disabled by default
// Okay var debugging = false // disabled by default
Questa regola non viene mai interpretata come richiesta o divieto di offerte spazio aggiuntivo all'inizio o alla fine di una riga; solo gli indirizzi spazio interno.
Costrutti specifici
Classi enum
Un'enumerazione senza funzioni e senza documentazione sulle sue costanti può facoltativamente essere formattata come una singola riga.
enum class Answer { YES, NO, MAYBE }
Quando le costanti di un'enumerazione vengono posizionate su righe separate, non è necessaria una riga vuota tra loro, tranne nel caso in cui definiscano un corpo.
enum class Answer { YES, NO, MAYBE { override fun toString() = """¯\_(ツ)_/¯""" } }
Poiché le classi enum sono classi, vengono applicate tutte le altre regole per le classi di formattazione.
Annotazioni
Le annotazioni di membri o tipi 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, potrebbe essere posizionato nella stessa riga della dichiarazione.
@Volatile var disposable: Disposable? = null @Test fun selectAll() { // … }
La sintassi @[...]
può essere utilizzata solo con un target di sito per l'utilizzo esplicito e solo per
che combina due o più annotazioni senza argomenti su un'unica riga.
@field:[JvmStatic Volatile] var disposable: Disposable? = null
Tipi di restituzione/proprietà impliciti
Se il corpo di una funzione di espressione o un inizializzatore di proprietà è uno scalare o il tipo restituito possa 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, mantieni la dichiarazione di tipo esplicita quando fa parte dell'API pubblica.
Denominazione
Gli identificatori utilizzano solo lettere e cifre ASCII e, in un numero limitato di casi indicati di seguito, trattini bassi. Pertanto, ogni nome di identificatore valido corrisponde all'espressione regolare \w+
.
Prefissi o suffissi speciali, come quelli mostrati negli esempi
name_
, mName
, s_name
e kName
non vengono utilizzati, tranne che nel caso di:
delle proprietà di supporto (vedi
Proprietà di supporto).
Nomi pacchetto
I nomi dei pacchetti sono tutti minuscoli e contengono parole consecutive concatenati (senza trattini bassi).
// Okay package com.example.deepspace // WRONG! package com.example.deepSpace // WRONG! package com.example.deep_space
Nomi dei tipi
I nomi delle classi sono scritti in PascalCase e di solito sono sostantivi
frasi chiave. Ad esempio, Character
o ImmutableList
. I nomi delle interfacce possono
essere anche sostantivi o frasi sostantivi (ad esempio, List
), ma
a volte possono essere aggettivi o espressioni aggettive
(ad esempio Readable
).
Il nome delle classi di test inizia con il nome della classe che stanno testando,
e termina con Test
. Ad esempio, HashTest
o
HashIntegrationTest
.
Nomi delle funzioni
I nomi delle funzioni sono scritti in camelCase e sono generalmente verbi o frasi di verbi. Ad esempio, sendMessage
o stop
.
Nei nomi delle funzioni di test possono essere visualizzati trattini bassi per separare i componenti logici del nome stesso.
@Test fun pop_emptyStack() { // … }
Le funzioni annotate con @Composable
che restituiscono Unit
sono maiuscole e minuscole e denominate come sostantivi, come se fossero tipi.
@Composable fun NameTag(name: String) { // … }
I nomi delle funzioni non devono contenere spazi perché non è supportato completamente supportata su Android.
// WRONG! fun `test every possible case`() {} // OK fun testEveryPossibleCase() {}
Nomi costanti
I nomi delle costanti utilizzano UPPER_SNAKE_CASE: tutte lettere maiuscole, con parole separate da trattini bassi. Ma cosa è una costante, esattamente?
Le costanti sono proprietà val
senza funzione get
personalizzata, i cui contenuti sono
sono profondamente immutabili e le cui funzioni non presentano effetti collaterali rilevabili. Questo
include tipi immutabili e raccolte immutabili di tipi immutabili
così come scalari e stringa, se contrassegnati come const
. Se una delle istanze
osservabile può cambiare, non è una costante. Semplicemente con l'intenzione di
non è sufficiente modificare mai l'oggetto.
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 sostantivi.
I valori costanti possono essere definiti solo all'interno di un object
o una dichiarazione di primo livello. Valori che altrimenti soddisfano il requisito
costante, ma definita all'interno di un valore class
, deve utilizzare un nome non costante.
Le costanti che sono valori scalari devono usare const
modificatore.
Nomi non costanti
I nomi non costanti sono scritti in camelCase. 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 sostantivi.
Proprietà di supporto
Quando proprietà di supporto , il suo nome deve corrispondere esattamente a quello della proprietà reale tranne che è preceduto da un trattino basso.
private var _table: Map<String, Int>? = null val table: Map<String, Int> get() { if (_table == null) { _table = HashMap() } return _table ?: throw AssertionError() }
Digita i nomi delle variabili
A ogni variabile di tipo viene assegnato un nome in uno dei due seguenti stili:
- Una sola lettera maiuscola, facoltativamente seguita da una
numero singolo (ad esempio
E
,T
,X
,T2
) - Un nome nel formato utilizzato per le classi, seguito dalla lettera maiuscola
lettera
T
(ad esempioRequestT
,FooBarT
)
Custodia in cammello
A volte c'è più di un modo ragionevole per convertire una frase inglese in "cammello", ad esempio quando sono presenti acronimi o costrutti insoliti come "IPv6" o "iOS". Per migliorare la prevedibilità, utilizza lo schema seguente.
Comincia con la prosa del nome:
- Converti la frase in ASCII normale e rimuovi eventuali apostrofi. Ad esempio, "algoritmo di Müller" potrebbe diventare "algoritmo di Müller".
- Dividi questo risultato in parole, dividendo in base agli spazi e all'eventuale punteggiatura rimanente (di solito i trattini). Consigliato: se una parola ha già un aspetto convenzionale a cammello nell'uso comune, suddividilo nelle sue parti costitutive (ad es. "Google Ads" diventa "parole dell'annuncio"). Tieni presente che una parola come "iOS" non è di per sé un caso d'uso. è in contrasto con qualsiasi convenzione, pertanto questo consiglio non si applica.
- Ora tutte le lettere devono essere minuscole (inclusi gli acronimi), quindi procedi in uno dei seguenti modi:
- Utilizza l'iniziale maiuscola per il primo carattere di ogni parola per ottenere il formato pascal.
- Deve usare l'iniziale maiuscola per il primo carattere di ogni parola, tranne il primo che restituisce. custodia a cammello.
- Infine, unisci tutte le parole in un unico identificatore.
Tieni presente che le lettere maiuscole e minuscole delle parole originali vengono quasi ignorate.
Modulo 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 di YouTube" | YouTubeImporter |
YoutubeImporter * |
(* Accettabile, ma sconsigliata.)
Documentazione
Formattazione
In questo esempio viene mostrata la formattazione di base dei blocchi KDoc:
/** * Multiple lines of KDoc text are written here, * wrapped normally… */ fun method(arg: String) { // … }
...o in questo esempio di una sola riga:
/** An especially short bit of KDoc. */
Il formato di base è sempre accettabile. Il modulo a una sola riga può essere
sostituiti quando l'intero blocco di documenti KDoc (inclusi gli indicatori di commento)
possono essere adattati su una sola riga. Tieni presente che ciò si applica solo quando non sono
che bloccano tag come @return
.
Paragrafi
Una riga vuota, ovvero una riga contenente solo l'asterisco iniziale allineato
(*
): compare tra i paragrafi e prima del gruppo di tag di blocco, se presente.
Blocca tag
Tutti i "tag di blocco" standard utilizzati appaiono nell'ordine
@constructor
, @receiver
, @param
, @property
, @return
,
@throws
, @see
, che non vengono mai visualizzati con una descrizione vuota.
Quando un tag di blocco non rientra su una sola riga,
le righe di continuazione sono rientrate di 4 spazi rispetto alla posizione di @
.
Frammento di riepilogo
Ogni blocco 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.
È un frammento, una frase sostantiva o verbale, non 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
con la punteggiatura completa.
Utilizzo
Come minimo, un documento KDoc è presente per ogni tipo public
,
e ogni membro public
o protected
di questo tipo,
con alcune eccezioni indicate di seguito.
Eccezione: funzioni autoesplicative
Il documento KDoc è facoltativo per funzioni "semplici e ovvie" come getFoo
e proprietà come foo
, nei casi in cui non c'è altro da dire se non "restituisce il foo".
Non è appropriato citare questa eccezione per giustificare l'omissione di elementi pertinenti
informazioni che un lettore tipico potrebbe avere bisogno di conoscere. Ad esempio, per
una funzione denominata getCanonicalName
o una proprietà denominata canonicalName
,
di non omettere la relativa documentazione (con il ragionamento che direbbe
/** Returns the canonical name. */
) se un lettore tipico potrebbe non avere
idea del termine "nome canonico" significa!
Eccezione: override
KDoc non è sempre presente su un metodo che sostituisce un metodo supertipo.