Dieses Dokument dient als vollständige Definition der Android-Programmierstandards von Google für Quellcode in der Programmiersprache Kotlin. Eine Kotlin-Quelldatei wird nur dann dem Google Android-Stil zugeordnet, wenn sie den hier genannten Regeln entspricht.
Wie bei anderen Programmierstilen werden auch hier nicht nur die Ästhetik der Formatierung behandelt, sondern auch andere Arten von Konventionen oder Codierungsstandards. Dieses Dokument konzentriert sich jedoch in erster Linie auf die strengen Regeln, die wir allgemein befolgen, und vermeidet Ratschläge, die nicht eindeutig durchsetzbar sind (ob durch Menschen oder Hilfsmittel).
Letzte Aktualisierung: 06.09.2023
Quelldateien
Alle Quelldateien müssen UTF-8-codiert sein.
Benennung
Wenn eine Quelldatei nur eine einzige Klasse der obersten Ebene enthält, sollte der Dateiname den Namen unter Berücksichtigung der Groß- und Kleinschreibung sowie die Erweiterung .kt
widerspiegeln. Wenn eine Quelldatei mehrere Deklarationen auf oberster Ebene enthält, wählen Sie einen Namen aus, der den Inhalt der Datei beschreibt, wenden Sie „PascalCase“ an (camelCase ist zulässig, wenn der Dateiname Plural ist) und hängen Sie die Erweiterung .kt
an.
// 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() = // …
Sonderzeichen
Leerzeichen
Abgesehen von der Zeilenabschlusssequenz ist das Horizontale Leerzeichen ASCII-Zeichen (0 x 20) das einzige Leerzeichen, das an einer beliebigen Stelle in einer Quelldatei angezeigt wird. Dies impliziert:
- Alle anderen Leerzeichen in String- und Zeichenliteralen werden maskiert.
- Tabulatorzeichen werden nicht für den Einzug verwendet.
Spezielle Escape-Sequenzen
Für jedes Zeichen mit einer speziellen Escape-Sequenz (\b
, \n
, \r
, \t
, \'
, \"
, \\
und \$
) wird diese Sequenz anstelle der entsprechenden Unicode-Sequenz (z.B. \u000a
) Esc-Taste.
Nicht-ASCII-Zeichen
Für die restlichen Nicht-ASCII-Zeichen wird entweder das tatsächliche Unicode-Zeichen (z.B. ∞
) oder dem entsprechenden Unicode-Escape-Zeichen (z.B. \u221e
) verwendet wird.
Die Wahl hängt nur davon ab, was den Code leichter zu lesen und zu verstehen macht.
Von Unicode-Escape-Zeichen wird bei druckbaren Zeichen an jeder Stelle abgeraten. Außerdem wird dringend davon abgeraten, außerhalb von Stringliteralen und Kommentaren zu arbeiten.
Beispiel | Diskussion |
---|---|
val unitAbbrev = "μs" |
Ideal: Bilder sind auch ohne Kommentar vollkommen verständlich. |
val unitAbbrev = "\u03bcs" // μs |
Schlecht: Es gibt keinen Grund, eine ausdruckbare Figur zu verwenden. |
val unitAbbrev = "\u03bcs" |
Schlecht: Der Leser weiß nicht, was das ist. |
return "\ufeff" + content |
Gut: Escapezeichen für nicht druckbare Zeichen verwenden und gegebenenfalls Kommentare hinzufügen |
Struktur
Eine .kt
-Datei enthält Folgendes (in dieser Reihenfolge):
- Überschrift für Urheberrecht und/oder Lizenz (optional)
- Anmerkungen auf Dateiebene
- Paketabrechnung
- Importanweisungen
- Deklarationen der obersten Ebene
Die einzelnen Abschnitte werden durch genau eine Leerzeile voneinander getrennt.
Urheberrecht / Lizenz
Wenn ein Urheberrechts- oder Lizenzheader in die Datei gehört, sollte er in einem mehrzeiligen Kommentar ganz oben platziert werden.
/* * Copyright 2017 Google, Inc. * * ... */
Verwenden Sie keinen KDoc-Stil oder einen einzeiligen Kommentar.
/** * Copyright 2017 Google, Inc. * * ... */
// Copyright 2017 Google, Inc. // // ...
Anmerkungen auf Dateiebene
Annotationen mit dem use-site-Ziel „file“ werden zwischen jedem Headerkommentar und der Paketdeklaration platziert.
Paketabrechnung
Die Paketanweisung unterliegt keinem Spaltenlimit und ist niemals mit Zeilenumbruch versehen.
Importanweisungen
Importanweisungen für Klassen, Funktionen und Eigenschaften werden in einer einzigen Liste und ASCII-Sortierung zusammengefasst.
Importe mit Platzhaltern (egal welchen Typs) sind nicht zulässig.
Ähnlich wie die Paketanweisung unterliegen Importanweisungen keinem Spaltenlimit und sie werden niemals in einen Zeilenumbruch gefasst.
Deklarationen der obersten Ebene
In einer .kt
-Datei können ein oder mehrere Typen, Funktionen, Attribute oder Typaliasse auf oberster Ebene deklariert werden.
Der Inhalt einer Datei sollte sich auf ein einzelnes Thema beziehen. Beispiele dafür sind ein einzelner öffentlicher Typ oder eine Reihe von Erweiterungsfunktionen, die denselben Vorgang für mehrere Empfängertypen ausführen. Nicht zusammenhängende Deklarationen sollten in separate Dateien getrennt und öffentliche Deklarationen in einer einzigen Datei minimiert werden.
Die Anzahl oder Reihenfolge der Inhalte einer Datei wird nicht explizit eingeschränkt.
Quelldateien werden in der Regel von oben nach unten gelesen, sodass im Allgemeinen die Reihenfolge, die weiter oben steht, Aufschluss darüber geben sollte, welche Deklarationen weiter unten stehen. Die Inhalte der Dateien werden möglicherweise unterschiedlich angeordnet. Ebenso kann eine Datei 100 Attribute, weitere 10 Funktionen und noch eine einzelne Klasse enthalten.
Wichtig ist, dass jede Datei eine eine logische Reihenfolge verwendet, die der Verwalter auf Anfrage erklären könnte. Neue Funktionen werden beispielsweise nicht nur gewohnheitsmäßig am Ende der Datei hinzugefügt, da dies eine chronologische Sortierung nach dem hinzugefügten Datum ergeben würde, was keine logische Reihenfolge ist.
Reihenfolge der Kursmitglieder
Die Reihenfolge der Mitglieder innerhalb einer Klasse folgt den gleichen Regeln wie die Deklarierung der obersten Ebene.
Formatierung
Zahnspangen
Für when
-Zweige und if
-Ausdrücke, die nicht mehr als einen else
-Zweig haben und in eine einzelne Zeile passen, sind keine Klammern erforderlich.
if (string.isEmpty()) return val result = if (string.isEmpty()) DEFAULT_VALUE else string when (value) { 0 -> return // … }
Ansonsten sind für alle if
-, for
-, when
-Zweig-, do
- und while
-Anweisungen und -Ausdrücke geschweifte Klammern erforderlich, auch wenn der Text leer ist oder nur eine einzelne Anweisung enthält.
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) }
Nicht leere Blöcke
Klammern folgen dem Kernighan- und Ritchie-Stil („ägyptische Klammern“) für nicht leere Blöcke und blockähnliche Konstrukte:
- Kein Zeilenumbruch vor der öffnenden geschweiften Klammer.
- Zeilenumbruch nach der öffnenden geschweiften Klammer.
- Zeilenumbruch vor der schließenden Klammer.
- Zeilenumbruch nach der schließenden Klammer, nur wenn diese Klammer eine Anweisung oder den Hauptteil einer Funktion, eines Konstruktors oder einer named-Klasse beendet.
Beispielsweise folgt nach der geschweiften Klammer kein Zeilenumbruch, wenn
else
oder ein Komma folgt.
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() } } }
Einige Ausnahmen für Enum-Klassen sind unten aufgeführt.
Leere Blöcke
Ein leerer Block oder ein blockähnliches Konstrukt muss im K&R-Stil vorliegen.
try { doSomething() } catch (e: Exception) {} // WRONG!
try { doSomething() } catch (e: Exception) { } // Okay
Ausdrücke
Eine if/else
-Bedingung, die als Ausdruck verwendet wird, darf nur dann geschweifte Klammern auslassen, wenn der gesamte Ausdruck in eine Zeile passt.
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 }
Einzug
Jedes Mal, wenn ein neuer Block oder ein neues blockähnliches Konstrukt geöffnet wird, vergrößert sich der Einzug um vier Leerzeichen. Wenn der Block endet, kehrt der Einzug zur vorherigen Einrückungsebene zurück. Die Einrückungsebene gilt sowohl für Code als auch für Kommentare im Block.
Eine Anweisung pro Zeile
Auf jede Anweisung folgt ein Zeilenumbruch. Semikolons werden nicht verwendet.
Zeilenumbruch
Der Code hat ein Spaltenlimit von 100 Zeichen. Abgesehen von den unten aufgeführten Ausnahmen müssen Zeilen, die dieses Limit überschreiten, wie unten erläutert einen Zeilenumbruch beinhalten.
Ausnahmen:
- Zeilen, in denen die Spaltenbeschränkung nicht eingehalten werden kann (z. B. eine lange URL in KDoc)
package
- undimport
-Anweisungen- Befehlszeilen in einem Kommentar, die per Ausschneiden und Einfügen in eine Shell eingefügt werden können
Wo soll ich brechen?
Die wichtigste Anweisung beim Zeilenumbruch lautet: Brechen Sie den Zeilenumbruch lieber auf einer höheren syntaktischen Ebene. Weitere Hinweise:
- Wenn eine Zeile bei einem Operator oder einer Infix-Funktionsnamen unterbrochen wird, kommt der Unterbrechung nach dem Namen des Operators oder der Infix-Funktion.
- Wird eine Linie an folgenden operatorähnlichen Symbolen unterbrochen, wird der Umbruch vor dem Symbol eingefügt:
- Das Punkttrennzeichen (
.
,?.
). - Die beiden Doppelpunkte eines Mitgliedsverweises (
::
).
- Das Punkttrennzeichen (
- Ein Methoden- oder Konstruktorname bleibt an der darauffolgenden öffnenden Klammer (
(
) angehängt. - Ein Komma (
,
) bleibt an das vorangehende Token angehängt. - Ein Lambda-Pfeil (
->
) bleibt an die vorausgegangene Argumentliste angehängt.
Funktionen
Wenn eine Funktionssignatur nicht in eine einzelne Zeile passt, trennen Sie jede Parameterdeklaration in eine eigene Zeile. Bei in diesem Format definierten Parametern sollte nur ein Einzug (+4) verwendet werden. Die schließende Klammer ()
) und der Rückgabetyp werden in einer eigenen Zeile ohne zusätzlichen Einzug platziert.
fun <T> Iterable<T>.joinToString( separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "" ): String { // … }
Ausdrucksfunktionen
Wenn eine Funktion nur einen einzigen Ausdruck enthält, kann sie als Ausdrucksfunktion dargestellt werden.
override fun toString(): String { return "Hey" }
override fun toString(): String = "Hey"
Properties
Wenn der Parameter der Eigenschaftsinitialisierung nicht in eine einzelne Zeile passt, brechen Sie den Zeilenumbruch nach dem Gleichheitszeichen (=
) ein und verwenden Sie einen Einzug.
private val defaultCharset: Charset? = EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)
Attribute, die eine get
- und/oder set
-Funktion deklarieren, sollten jeweils in einer eigenen Zeile mit einem normalen Einzug (+4) platziert werden. Formatieren Sie sie nach den
gleichen Regeln wie für Funktionen.
var directory: File? = null set(value) { // … }Bei schreibgeschützten Properties kann eine kürzere Syntax verwendet werden, die in eine einzelne Zeile passt.
val defaultExtension: String get() = "kt"
Leerraum
Vertikal
Eine einzelne Leerzeile wird angezeigt:
- Zwischen aufeinanderfolgenden Mitgliedern einer Klasse: Attribute, Konstruktoren, Funktionen, verschachtelte Klassen usw.
- Ausnahme: Eine leere Zeile zwischen zwei aufeinanderfolgenden Attributen (ohne weiteren Code) ist optional. Solche Leerzeilen werden nach Bedarf verwendet, um logische Gruppierungen von Properties zu erstellen und Properties mit ihren unterstützenden Properties zu verknüpfen, sofern vorhanden.
- Ausnahme: Leere Zeilen zwischen enum-Konstanten werden unten beschrieben.
- Zwischen Anweisungen, nach Bedarf, um den Code in logische Unterabschnitte zu organisieren.
- Optional vor der ersten Anweisung in einer Funktion, vor dem ersten Mitglied einer Klasse oder nach dem letzten Element einer Klasse (weder empfohlen noch nicht empfohlen).
- Wenn dies in anderen Abschnitten dieses Dokuments erforderlich ist, z. B. im Abschnitt Struktur.
Mehrere aufeinanderfolgende Leerzeilen sind zulässig, werden aber nicht empfohlen oder sind überhaupt nicht erforderlich.
Horizontal
Neben den von der Sprache oder anderen Stilregeln geforderten Vorgaben und abgesehen von Literalen, Kommentaren und KDoc wird ein einzelnes ASCII-Leerzeichen auch nur an folgenden Stellen angezeigt:
- Trennen Sie alle reservierten Wörter wie
if
,for
odercatch
durch eine offene Klammer ((
), die in dieser Zeile darauf folgt.// WRONG! for(i in 0..1) { }
// Okay for (i in 0..1) { }
- Trennung eines reservierten Wortes, z. B.
else
odercatch
, durch eine schließende geschweifte Klammer (}
), die in dieser Zeile vorangestellt ist.// WRONG! }else { }
// Okay } else { }
-
Vor einer offenen geschweiften Klammer (
{
).// WRONG! if (list.isEmpty()){ }
// Okay if (list.isEmpty()) { }
-
Auf beiden Seiten jedes binären Operators.
// WRONG! val two = 1+1
// Okay val two = 1 + 1
Das gilt auch für die folgenden Symbole, die einem Operator ähneln:- Pfeil in einem Lambda-Ausdruck (
->
).// WRONG! ints.map { value->value.toString() }
// Okay ints.map { value -> value.toString() }
-
die beiden Doppelpunkte (
::
) eines Mitgliedsverweises.// WRONG! val toString = Any :: toString
// Okay val toString = Any::toString
-
das Punkttrennzeichen (
.
).// WRONG it . toString()
// Okay it.toString()
-
den Bereichsoperator (
..
)// WRONG for (i in 1 .. 4) { print(i) }
// Okay for (i in 1..4) { print(i) }
- Pfeil in einem Lambda-Ausdruck (
-
Vor einem Doppelpunkt (
:
), wenn er in einer Klassendeklaration zum Angeben einer oder mehrerer Basisklasse(s) oder in einerwhere
-Klausel für allgemeine Einschränkungen verwendet wird.// 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>
-
Nach einem Komma (
,
) oder Doppelpunkt (:
).// WRONG! val oneAndTwo = listOf(1,2)
// Okay val oneAndTwo = listOf(1, 2)
// WRONG! class Foo :Runnable
// Okay class Foo : Runnable
-
Auf beiden Seiten des doppelten Schrägstrichs (
//
), mit dem ein Kommentar am Zeilenende beginnt. Hier sind mehrere Leerzeichen zulässig, aber nicht erforderlich.// WRONG! var debugging = false//disabled by default
// Okay var debugging = false // disabled by default
Diese Regel wird nie so ausgelegt, dass zusätzliche Leerzeichen am Anfang oder Ende einer Zeile erforderlich oder verboten sind. Sie bezieht sich nur auf den Innenraum.
Spezifische Konstrukte
Enum-Klassen
Ein Enum ohne Funktionen und ohne Dokumentation zu seinen Konstanten kann optional als eine Zeile formatiert werden.
enum class Answer { YES, NO, MAYBE }
Wenn die Konstanten in einer Enum in separaten Zeilen stehen, ist zwischen ihnen keine Leerzeile erforderlich, es sei denn, sie definieren einen Textkörper.
enum class Answer { YES, NO, MAYBE { override fun toString() = """¯\_(ツ)_/¯""" } }
Da es sich bei enum-Klassen um Klassen handelt, gelten alle anderen Regeln für Formatierungsklassen.
Anmerkungen
Mitglieder- oder Typanmerkungen werden in separaten Zeilen direkt vor dem annotierten Konstrukt platziert.
@Retention(SOURCE) @Target(FUNCTION, PROPERTY_SETTER, FIELD) annotation class Global
Anmerkungen ohne Argumente können in einer einzelnen Zeile eingefügt werden.
@JvmField @Volatile var disposable: Disposable? = null
Wenn nur eine Annotation ohne Argumente vorhanden ist, kann sie in dieselbe Zeile wie die Deklaration eingefügt werden.
@Volatile var disposable: Disposable? = null @Test fun selectAll() { // … }
Die @[...]
-Syntax darf nur mit einem expliziten Ziel der Nutzungswebsite verwendet werden und nur zum Kombinieren von zwei oder mehr Anmerkungen ohne Argumente in einer einzigen Zeile.
@field:[JvmStatic Volatile] var disposable: Disposable? = null
Implizite Rückgabe-/Eigenschaftstypen
Wenn ein Ausdrucksfunktionstext oder ein Eigenschaftsinitialisierer ein skalarer Wert ist oder der Rückgabetyp klar aus dem Text abgeleitet werden kann, kann er weggelassen werden.
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")
Behalten Sie beim Schreiben einer Bibliothek die explizite Typdeklaration bei, wenn sie Teil der öffentlichen API ist.
Benennung
Kennungen verwenden nur ASCII-Buchstaben und -Ziffern und, in einigen wenigen unten genannten Fällen, Unterstriche. Somit entspricht jeder gültige Kennzeichnungsname dem regulären Ausdruck \w+
.
Spezielle Präfixe oder Suffixe wie in den Beispielen name_
, mName
, s_name
und kName
werden nur im Fall von unterstützenden Attributen verwendet (siehe Sicherungsattribute).
Paketnamen
Paketnamen werden alle in Kleinbuchstaben geschrieben und aufeinander folgende Wörter einfach verkettet (keine Unterstriche).
// Okay package com.example.deepspace // WRONG! package com.example.deepSpace // WRONG! package com.example.deep_space
Typnamen
Klassennamen werden im PascalCase geschrieben und sind in der Regel Substantive oder Nominalsätze. Beispiel: Character
oder ImmutableList
. Benutzeroberflächennamen können auch Substantive oder Nominalsätze sein (z. B. List
), manchmal jedoch auch Adjektive oder Adjektive (z. B. Readable
).
Die Namen von Testklassen beginnen mit dem Namen der Klasse, die sie testen, und enden mit Test
. Beispiel: HashTest
oder HashIntegrationTest
.
Funktionsnamen
Funktionsnamen werden in CamelCase geschrieben und sind in der Regel Verben oder Verbformulierungen. Beispiel: sendMessage
oder stop
.
Unterstriche sind in Testfunktionsnamen zulässig, um die logischen Komponenten des Namens zu trennen.
@Test fun pop_emptyStack() { // … }
Mit @Composable
annotierte Funktionen, die Unit
zurückgeben, sind PascalCased und werden wie Substantive benannt.
@Composable fun NameTag(name: String) { // … }
Funktionsnamen sollten keine Leerzeichen enthalten, da dies nicht auf jeder Plattform unterstützt wird. Insbesondere ist dies in Android nicht vollständig möglich.
// WRONG! fun `test every possible case`() {} // OK fun testEveryPossibleCase() {}
Konstantennamen
Für Konstantennamen wird UPPER_SNAKE_CASE verwendet: nur Großbuchstaben, wobei Wörter durch Unterstriche getrennt sind. Aber was genau ist eine Konstante?
Konstanten sind val
-Attribute ohne benutzerdefinierte get
-Funktion, deren Inhalte völlig unveränderlich sind und deren Funktionen keine erkennbaren Nebeneffekte haben. Dazu gehören unveränderliche Typen und unveränderliche Sammlungen unveränderlicher Typen sowie Skalare und Strings, wenn sie mit const
gekennzeichnet sind. Wenn sich der beobachtbare Status einer Instanz ändern kann, ist er keine Konstante. Die bloße Absicht, das Objekt nie zu ändern, reicht nicht aus.
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()
Diese Namen sind in der Regel Substantive oder Nominalsätze.
Konstante Werte können nur innerhalb eines object
oder als Deklaration auf oberster Ebene definiert werden. Werte, die ansonsten die Anforderung einer Konstanten erfüllen, aber in einer class
definiert sind, müssen einen nicht konstanten Namen haben.
Für Konstanten, die skalare Werte sind, muss der Modifizierer const
verwendet werden.
Nicht konstante Namen
Nicht konstante Namen werden in CamelCase geschrieben. Diese gelten für Instanzeigenschaften, lokale Eigenschaften und Parameternamen.
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")
Diese Namen sind in der Regel Substantive oder Nominalsätze.
Sicherungseigenschaften
Wenn ein unterstützendes Attribut benötigt wird, muss sein Name genau mit dem des realen Attributs übereinstimmen, es sei denn, es muss ein Unterstrich vorangestellt werden.
private var _table: Map? = null val table: Map get() { if (_table == null) { _table = HashMap() } return _table ?: throw AssertionError() }
Variablennamen eingeben
Jede Typvariable wird in einem von zwei Stilen benannt:
- Ein einzelner Großbuchstaben, optional gefolgt von einer einzelnen Ziffer (z. B.
E
,T
,X
,T2
) - Ein Name in der für Klassen verwendeten Form, gefolgt vom Großbuchstaben
T
(z. B.RequestT
,FooBarT
)
CamelCase
Manchmal gibt es mehrere vernünftige Möglichkeiten, eine englische Phrase in die Camel-Case-Schreibweise umzuwandeln, z. B. wenn Akronyme oder ungewöhnliche Konstrukte wie „IPv6“ oder „iOS“ vorhanden sind. Verwenden Sie das folgende Schema, um die Vorhersehbarkeit zu verbessern.
Beginnend mit der Prosaform des Namens:
- Konvertieren Sie die Wortgruppe in einfachen ASCII-Code und entfernen Sie alle Apostrophe. So könnte beispielsweise „Müllers Algorithmus“ zu „Muellers-Algorithmus“ werden.
- Teilen Sie dieses Ergebnis in Wörter auf, indem Sie Leerzeichen und verbleibende Satzzeichen (in der Regel Bindestriche) verwenden. Empfohlen:Wenn ein Wort bereits die übliche Schreibweise eines Wortes mit Camel-Case-Schreibweise aufweist, teilen Sie es in seine Bestandteile auf (z.B. „AdWords“ wird zu „Anzeigenwörtern“). Ein Wort wie „iOS“ entspricht nicht wirklich der Camel-Case-Schreibweise, da es gegen alle Konventionen verstößt, sodass diese Empfehlung nicht zutrifft.
- Schreiben Sie jetzt alles in Kleinbuchstaben (einschließlich Akronyme) und führen Sie dann einen der folgenden Schritte aus:
- Schreiben Sie das erste Zeichen jedes Wortes groß, um die Schreibweise „pascal“ zu verwenden.
- Schreiben Sie das erste Zeichen jedes Wortes außer dem ersten groß, um die Camel-Case-Schreibweise zu erhalten.
- Abschließend müssen Sie alle Wörter zu einer einzigen Kennung zusammenführen.
Beachten Sie, dass die Groß- und Kleinschreibung der ursprünglichen Wörter fast vollständig ignoriert wird.
Prose-Formular | Richtig | Falsch |
---|---|---|
„XML-HTTP-Anfrage“ | XmlHttpRequest |
XMLHTTPRequest |
„neue Kundennummer“ | newCustomerId |
newCustomerID |
„innere Stoppuhr“ | innerStopwatch |
innerStopWatch |
„unterstützt IPv6 unter iOS“ | supportsIpv6OnIos |
supportsIPv6OnIOS |
„YouTube Importeur“ | YouTubeImporter |
YoutubeImporter * |
(* Zulässig, aber nicht empfohlen.)
Dokumentation
Formatierung
Die grundlegende Formatierung von KDoc-Blöcken wird in diesem Beispiel veranschaulicht:
/** * Multiple lines of KDoc text are written here, * wrapped normally… */ fun method(arg: String) { // … }
...oder in diesem einzeiligen Beispiel:
/** An especially short bit of KDoc. */
Das grundlegende Formular ist immer zulässig. Die einzeilige Form kann ersetzt werden, wenn der gesamte KDoc-Block (einschließlich Kommentarmarkierungen) in eine einzige Zeile passt. Dies gilt nur, wenn keine Block-Tags wie @return
vorhanden sind.
Absätze
Zwischen den Absätzen und vor der Gruppe von Block-Tags, falls vorhanden, wird eine Leerzeile – also eine Zeile, die nur das führende Sternchen (*
) enthält, eingefügt.
Tags blockieren
Alle Standard-Blockier-Tags, die in der Reihenfolge @constructor
, @receiver
, @param
, @property
, @return
, @throws
, @see
verwendet werden, erscheinen nie ohne leere Beschreibung.
Wenn ein Block-Tag nicht in eine einzelne Zeile passt, werden Fortsetzungszeilen um vier Leerzeichen gegenüber der Position von @
eingerückt.
Zusammenfassungsfragment
Jeder KDoc-Block beginnt mit einem kurzen Zusammenfassungsfragment. Dieses Fragment ist sehr wichtig: Es ist der einzige Teil des Textes, der in bestimmten Kontexten wie Klassen- und Methodenindexen angezeigt wird.
Dies ist ein Fragment – eine Nominalphrase oder eine Verbformulierung, kein vollständiger Satz.
Er beginnt nicht mit „A `Foo` is a...
“ oder „This method returns...
“ und muss auch keinen vollständigen imperativen Satz wie „Save the record.
“ bilden. Das Fragment wird jedoch großgeschrieben und die Satzzeichen verwenden, als wäre es ein vollständiger Satz.
Nutzung
KDoc ist mindestens für jeden public
-Typ und jedes public
- oder protected
-Mitglied dieses Typs vorhanden. Es gibt jedoch einige Ausnahmen, die unten aufgeführt sind.
Ausnahme: selbsterklärende Funktionen
KDoc ist optional für „einfache, offensichtliche“ Funktionen wie getFoo
und Attribute wie foo
, wenn es wirklich nichts wert ist, zu sagen, dass es nur „gibt den foo zurück“.
Es ist nicht angemessen, diese Ausnahme angeführt zu haben, um das Weglassen relevanter Informationen zu rechtfertigen, die ein typischer Leser möglicherweise wissen muss. Bei einer Funktion mit dem Namen getCanonicalName
oder einer Property mit dem Namen canonicalName
solltest du beispielsweise die Dokumentation (mit der Begründung, dass nur /** Returns the canonical name. */
lauten würde) nicht ausgelassen, wenn ein typischer Leser vielleicht keine Ahnung hat, was der Begriff „kanonischer Name“ bedeutet.
Ausnahme: Überschreibungen
KDoc ist bei einer Methode, die eine Supertype-Methode überschreibt, nicht immer vorhanden.