Dieses Dokument enthält die vollständige Definition der Android-Codierungsstandards von Google für Quellcode in der Programmiersprache Kotlin. Eine Kotlin-Quelldatei wird als „Google Android Style“ bezeichnet, wenn sie den hier beschriebenen Regeln entspricht.
Wie bei anderen Programmierstilrichtlinien geht es nicht nur um ästhetische Formatierungsprobleme, sondern auch um andere Arten von Konventionen oder Codierungsstandards. In diesem Dokument geht es jedoch hauptsächlich um die verbindlichen Regeln, die wir universell anwenden. Es werden keine Ratschläge gegeben, die nicht eindeutig durchgesetzt werden können (weder von Menschen noch von Tools).
Letzte Aktualisierung: 06.09.2023
Quelldateien
Alle Quelldateien müssen als UTF-8 codiert sein.
Benennung
Wenn eine Quelldatei nur eine einzelne Klasse der obersten Ebene enthält, sollte der Dateiname den Namen (mit Berücksichtigung der Groß- und Kleinschreibung) plus die Erweiterung .kt enthalten. Wenn eine Quelldatei mehrere Deklarationen auf oberster Ebene enthält, wählen Sie einen Namen, der den Inhalt der Datei beschreibt, wenden Sie PascalCase an (camelCase ist akzeptabel, wenn der Dateiname im Plural steht) und hängen Sie die Erweiterung .kt an.
// MyClass.kt class MyClass { }
// Bar.kt class Bar { } fun Runnable.toBar(): Bar = Bar()
// Map.kt fun <T, O> Set<T>.map(func: (T) -> O): List<O> = emptyList() fun <T, O> List<T>.map(func: (T) -> O): List<O> = emptyList()
// extensions.kt fun MyClass.process() = { /* ... */ } fun MyResult.print() = { /* ... */ }
Sonderzeichen
Leerzeichen
Abgesehen von der Zeilenabschlusssequenz ist das ASCII-Leerzeichen (0x20) das einzige Leerzeichen, das in einer Quelldatei vorkommt. Das bedeutet:
- Alle anderen Whitespace-Zeichen in String- und Zeichenliteralen werden maskiert.
- Tabulatoren werden nicht für die Einrückung verwendet.
Spezielle Escapesequenzen
Für jedes Zeichen, das eine spezielle Escape-Sequenz hat (\b, \n, \r, \t, \', \", \\ und \$), wird diese Sequenz anstelle des entsprechenden Unicode-Escapes (z.B. \u000a) verwendet.
Nicht-ASCII-Zeichen
Für die verbleibenden Nicht-ASCII-Zeichen wird entweder das tatsächliche Unicode-Zeichen (z.B. ∞) oder das entsprechende Unicode-Escape-Zeichen (z.B. \u221e) verwendet.
Die Entscheidung hängt nur davon ab, was den Code leichter lesbar und verständlich macht.
Unicode-Escapes werden für druckbare Zeichen an beliebiger Stelle nicht empfohlen und sind außerhalb von Stringliteralen und Kommentaren nicht zulässig.
| Beispiel | Diskussion |
|---|---|
val unitAbbrev = "μs" |
Am besten: vollkommen klar, auch ohne Kommentar. |
val unitAbbrev = "\u03bcs" // μs |
Schlecht: Es gibt keinen Grund, ein Escapezeichen mit einem druckbaren Zeichen zu verwenden. |
val unitAbbrev = "\u03bcs" |
Schlecht: Der Leser hat keine Ahnung, was das ist. |
return "\ufeff" + content |
Gut: Verwenden Sie Escape-Sequenzen für nicht druckbare Zeichen und fügen Sie bei Bedarf Kommentare hinzu. |
Struktur
Eine .kt-Datei besteht aus den folgenden Elementen in der angegebenen Reihenfolge:
- Header für Urheberrecht und/oder Lizenz (optional)
- Anmerkungen auf Dateiebene
- Paketübersicht
- Importanweisungen
- Deklarationen der obersten Ebene
Die einzelnen Abschnitte sind durch genau eine leere Zeile getrennt.
Urheberrecht / Lizenz
Wenn ein Urheberrechts- oder Lizenzheader in die Datei gehört, sollte er ganz oben in einem mehrzeiligen Kommentar platziert werden.
/* * Copyright 2017 Google, Inc. * * ... */
Verwenden Sie keinen Kommentar im KDoc-Stil oder im einzeiligen Stil.
/** * Copyright 2017 Google, Inc. * * ... */
// Copyright 2017 Google, Inc. // // ...
Anmerkungen auf Dateiebene
Anmerkungen mit dem Use-Site-Ziel „file“ werden zwischen einem beliebigen Header-Kommentar und der Paketdeklaration platziert.
Paketübersicht
Für die Paketdeklaration gilt kein Spaltenlimit und sie wird nie umgebrochen.
Importanweisungen
Importanweisungen für Klassen, Funktionen und Eigenschaften werden in einer einzigen Liste zusammengefasst und nach ASCII sortiert.
Platzhalterimporte (jeglicher Art) sind nicht zulässig.
Ähnlich wie bei der Package-Anweisung unterliegen Importanweisungen kein Spaltenlimit und werden nie umgebrochen.
Deklarationen der obersten Ebene
In einer .kt-Datei können ein oder mehrere Typen, Funktionen, Eigenschaften oder Typ-Aliase auf der obersten Ebene deklariert werden.
Der Inhalt einer Datei sollte sich auf ein einzelnes Thema konzentrieren. Beispiele hierfü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 aufgeteilt werden. Öffentliche Deklarationen in einer einzelnen Datei sollten minimiert werden.
Für die Anzahl oder Reihenfolge der Inhalte einer Datei gibt es keine expliziten Einschränkungen.
Quellcode wird in der Regel von oben nach unten gelesen. Die Reihenfolge sollte daher so sein, dass die Deklarationen weiter oben das Verständnis der Deklarationen weiter unten unterstützen. In verschiedenen Dateien können die Inhalte unterschiedlich angeordnet sein. Eine Datei kann beispielsweise 100 Properties, eine andere 10 Funktionen und eine dritte eine einzelne Klasse enthalten.
Wichtig ist, dass jede Datei eine logische Reihenfolge hat, die der Verantwortliche auf Anfrage erklären kann. Neue Funktionen werden beispielsweise nicht einfach am Ende der Datei hinzugefügt, da dies zu einer chronologischen Sortierung nach dem Datum des Hinzufügens führen würde, was keine logische Sortierung ist.
Reihenfolge der Kursmitglieder
Die Reihenfolge der Elemente in einer Klasse folgt denselben Regeln wie die Deklarationen auf oberster Ebene.
Formatierung
Zahnspangen
Geschweifte Klammern sind für when-Zweige und if-Ausdrücke nicht erforderlich, die nicht mehr als einen else-Zweig haben und in eine einzelne Zeile passen.
if (string.isEmpty()) return val result = if (string.isEmpty()) DEFAULT_VALUE else string when (value) { 0 -> return // … }
Geschweifte Klammern sind ansonsten für alle if-, for-, when-Verzweigungen, do- und while-Anweisungen und ‑Ausdrücke erforderlich, auch wenn der Rumpf 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
Geschweifte Klammern folgen dem Kernighan-und-Ritchie-Stil („ägyptische Klammern“) für nicht leere Blöcke und blockartige Konstrukte:
- Vor der öffnenden geschweiften Klammer darf kein Zeilenumbruch stehen.
- Zeilenumbruch nach der öffnenden geschweiften Klammer.
- Zeilenumbruch vor der schließenden geschweiften Klammer.
- Zeilenumbruch nach der schließenden geschweiften Klammer, nur wenn diese Klammer eine Anweisung oder den Rumpf einer Funktion, eines Konstruktors oder einer benannten Klasse beendet.
Beispiel: Nach der geschweiften Klammer gibt es keinen Zeilenumbruch, wenn danach
elseoder 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 sein.
try { doSomething() } catch (e: Exception) {} // WRONG!
try { doSomething() } catch (e: Exception) { } // Okay
Ausdrücke
Bei einer if/else-Bedingung, die als Ausdruck verwendet wird, können die geschweiften Klammern nur weggelassen werden, 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 blockähnliches Konstrukt geöffnet wird, wird die Einrückung um vier Leerzeichen erhöht. Wenn der Block endet, wird die Einrückung auf die vorherige Einrückungsebene zurückgesetzt. Die Einzugsebene gilt für Code und Kommentare im gesamten Block.
Eine Anweisung pro Zeile
Auf jede Anweisung folgt ein Zeilenumbruch. Es werden keine Semikolons verwendet.
Zeilenumbruch
Der Code darf maximal 100 Zeichen pro Spalte umfassen. Sofern unten nicht anders angegeben, muss jede Zeile, die dieses Limit überschreitet, umgebrochen werden (siehe unten).
Ausnahmen:
- Zeilen, in denen das Spaltenlimit nicht eingehalten werden kann (z. B. eine lange URL in KDoc)
package- undimport-Anweisungen- Befehlszeilen in einem Kommentar, die in eine Shell kopiert und eingefügt werden können
Wo kann ich eine Pause einlegen?
Die wichtigste Regel für den Zeilenumbruch lautet: Bevorzuge es, auf einer höheren syntaktischen Ebene umzubrechen. Weitere Hinweise:
- Wenn eine Zeile an einem Operator oder Infix-Funktionsnamen umgebrochen wird, erfolgt der Umbruch nach dem Operator oder Infix-Funktionsnamen.
- Wenn eine Zeile an den folgenden „operatorähnlichen“ Symbolen umgebrochen wird, erfolgt der Umbruch vor dem Symbol:
- Das Punkt-Trennzeichen (
.,?.). - Die beiden Doppelpunkte einer Mitgliedsreferenz (
::).
- Das Punkt-Trennzeichen (
- Ein Methoden- oder Konstruktornamen bleibt an der öffnenden Klammer (
() angehängt, die darauf folgt. - Ein Komma (
,) bleibt an das Token angehängt, das vor ihm steht. - Ein Lambda-Pfeil (
->) bleibt an die Argumentliste angehängt, die ihm vorangestellt ist.
Funktionen
Wenn eine Funktionssignatur nicht in eine einzelne Zeile passt, muss jede Parameterdeklaration in einer eigenen Zeile stehen. Parameter, die in diesem Format definiert sind, sollten mit einem einzelnen Einzug (+4) versehen werden. Die schließende Klammer ()) und der Rückgabetyp werden in einer eigenen Zeile ohne zusätzliche Einrückung 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 eine Attributinitialisierung nicht in eine Zeile passt, brechen Sie nach dem Gleichheitszeichen (=) um und verwenden Sie einen Einzug.
private val defaultCharset: Charset? = EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)
Eigenschaften, die eine get- und/oder set-Funktion deklarieren, sollten jeweils in einer eigenen Zeile mit normalem Einzug (+4) stehen. Formatieren Sie sie nach denselben Regeln wie Funktionen.
var directory: File? = null set(value) { // … }
val defaultExtension: String get() = "kt"
Leerzeichen
Vertikal
Es wird eine einzelne leere Zeile angezeigt:
- Zwischen aufeinanderfolgenden Mitgliedern einer Klasse: Attribute, Konstruktoren, Funktionen, verschachtelte Klassen usw.
- Ausnahme:Eine leere Zeile zwischen zwei aufeinanderfolgenden Properties (ohne anderen Code dazwischen) ist optional. Solche Leerzeilen werden nach Bedarf verwendet, um logische Gruppierungen von Attributen zu erstellen und Attribute mit dem zugrunde liegenden Attribut zu verknüpfen, sofern vorhanden.
- Ausnahme:Leere Zeilen zwischen Enum-Konstanten werden unten behandelt.
- Zwischen Anweisungen, nach Bedarf, um den Code in logische Unterabschnitte zu unterteilen.
- Optional vor der ersten Anweisung in einer Funktion, vor dem ersten Element einer Klasse oder nach dem letzten Element einer Klasse (weder empfohlen noch abgeraten).
- Wie in anderen Abschnitten dieses Dokuments (z. B. im Abschnitt Struktur) beschrieben.
Mehrere aufeinanderfolgende Leerzeilen sind zulässig, aber nicht empfehlenswert oder erforderlich.
Horizontal
Abgesehen von Literalen, Kommentaren und KDoc wird ein einzelnes ASCII-Leerzeichen nur an den folgenden Stellen verwendet, sofern dies nicht durch die Sprach- oder anderen Stilregeln erforderlich ist:
- Trennen Sie alle reservierten Wörter wie
if,forodercatchvon einer öffnenden Klammer ((), die in derselben Zeile folgt.// WRONG! for(i in 0..1) { }
// Okay for (i in 0..1) { }
- Trennen Sie alle reservierten Wörter wie
elseodercatchvon einer schließenden geschweiften Klammer (}), die in derselben Zeile vor dem Wort steht.// WRONG! }else { }
// Okay } else { }
-
Vor einer öffnenden geschweiften Klammer (
{).// WRONG! if (list.isEmpty()){ }
// Okay if (list.isEmpty()) { }
-
Auf beiden Seiten eines binären Operators.
// WRONG! val two = 1+1
Dies gilt auch für die folgenden operatorähnlichen Symbole:// Okay val two = 1 + 1
- der Pfeil in einem Lambda-Ausdruck (
->).// WRONG! ints.map { value->value.toString() }
// Okay ints.map { value -> value.toString() }
-
die beiden Doppelpunkte (
::) einer Mitgliederreferenz.// WRONG! val toString = Any :: toString
// Okay val toString = Any::toString
-
das Punkt-Trennzeichen (
.).// WRONG it . toString()
// Okay it.toString()
-
dem Bereichsoperator (
..).// WRONG for (i in 1 .. 4) { print(i) }
// Okay for (i in 1..4) { print(i) }
- der Pfeil in einem Lambda-Ausdruck (
-
Vor einem Doppelpunkt (
:) nur, wenn er in einer Klassendeklaration zum Angeben einer Basisklasse oder von Schnittstellen verwendet wird oder wenn er in einerwhere-Klausel für generische 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<T>> 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 Zeilenendkommentar 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 interpretiert, dass zusätzlicher Leerraum am Anfang oder Ende einer Zeile erforderlich oder verboten ist. Sie bezieht sich nur auf den Leerraum im Inneren.
Spezifische Konstrukte
Enum-Klassen
Ein Enum ohne Funktionen und ohne Dokumentation zu seinen Konstanten kann optional als einzelne Zeile formatiert werden.
enum class Answer { YES, NO, MAYBE }
Wenn die Konstanten in einem Enum in separaten Zeilen stehen, ist zwischen ihnen keine Leerzeile erforderlich, es sei denn, sie definieren einen Body.
enum class Answer { YES, NO, MAYBE { override fun toString() = """¯\_(ツ)_/¯""" } }
Da Enum-Klassen Klassen sind, gelten alle anderen Regeln für die Formatierung von Klassen.
Annotationen
Mitglieds- oder Typanmerkungen werden unmittelbar vor dem annotierten Konstrukt in separaten Zeilen platziert.
@Retention(SOURCE) @Target(FUNCTION, PROPERTY_SETTER, FIELD) annotation class Global
Anmerkungen ohne Argumente können in einer einzelnen Zeile platziert werden.
@JvmField @Volatile var disposable: Disposable? = null
Wenn nur eine einzelne Annotation ohne Argumente vorhanden ist, kann sie in derselben Zeile wie die Deklaration platziert werden.
@Volatile var disposable: Disposable? = null @Test fun selectAll() { // … }
Die @[...]-Syntax darf nur mit einem expliziten Use-Site-Ziel verwendet werden und nur zum Kombinieren von mindestens zwei Anmerkungen ohne Argumente in einer einzelnen Zeile.
@field:[JvmStatic Volatile] var disposable: Disposable? = null
Implizite Rückgabe-/Eigenschaftstypen
Wenn der Rumpf einer Ausdrucksfunktion oder ein Eigenschaftsinitialisierer ein Skalarwert ist oder der Rückgabetyp eindeutig aus dem Rumpf 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
Für Kennungen werden nur ASCII-Buchstaben und -Ziffern und in wenigen unten aufgeführten Fällen Unterstriche verwendet. Jeder gültige Kennzeichnungsname wird also durch den regulären Ausdruck \w+ abgeglichen.
Spezielle Präfixe oder Suffixe wie in den Beispielen name_, mName, s_name und kName werden nicht verwendet, außer bei unterstützenden Eigenschaften (siehe Unterstützende Eigenschaften).
Paketnamen
Paketnamen bestehen nur aus Kleinbuchstaben. Aufeinanderfolgende Wörter werden einfach aneinandergehängt (keine Unterstriche).
// Okay package com.example.deepspace // WRONG! package com.example.deepSpace // WRONG! package com.example.deep_space
Typnamen
Klassennamen werden in PascalCase geschrieben und sind in der Regel Substantive oder Wortgruppen mit Substantiven. Beispiel: Character oder ImmutableList. Schnittstellennamen können auch Substantive oder Wortgruppen sein (z. B. List), manchmal aber auch Adjektive oder Wortgruppen (z. B. Readable).
Testklassen beginnen mit dem Namen der Klasse, die getestet wird, und enden mit Test. Beispiel: HashTest oder HashIntegrationTest.
Funktionsnamen
Funktionsnamen werden in CamelCase geschrieben und sind in der Regel Verben oder Verbphrasen. Beispiel: sendMessage oder stop.
Unterstriche sind in Testfunktionsnamen zulässig, um logische Komponenten des Namens zu trennen.
@Test fun pop_emptyStack() { // … }
Funktionen, die mit @Composable annotiert sind und Unit zurückgeben, werden im PascalCase-Format geschrieben und als Substantive benannt, als wären sie Typen.
@Composable fun NameTag(name: String) { // … }
Funktionsnamen sollten keine Leerzeichen enthalten, da dies nicht auf allen Plattformen unterstützt wird (insbesondere nicht vollständig auf Android).
// WRONG! fun `test every possible case`() {} // OK fun testEveryPossibleCase() {}
Konstantennamen
Konstantennamen werden in UPPER_SNAKE_CASE geschrieben: alle Buchstaben in Großbuchstaben, Wörter durch Unterstriche getrennt. Aber was ist eine Konstante genau?
Konstanten sind val-Eigenschaften ohne benutzerdefinierte get-Funktion, deren Inhalt unveränderlich ist 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 als const gekennzeichnet sind. Wenn sich ein beobachtbarer Zustand einer Instanz ändern kann, ist sie keine Konstante. Es reicht nicht aus, nur die Absicht zu haben, das Objekt nie zu ändern.
const val NUMBER = 5 val NAMES = listOf("Alice", "Bob") val AGES = mapOf("Alice" to 35, "Bob" to 32) val COMMA_JOINED = NAMES.joinToString(", ") val EMPTY_ARRAY = arrayOf<SomeMutableType>()
Diese Namen sind in der Regel Substantive oder Wortgruppen mit Substantiven.
Konstante Werte können nur innerhalb eines object oder als Deklaration der obersten Ebene definiert werden. Werte, die ansonsten die Anforderung einer Konstanten erfüllen, aber innerhalb von class definiert sind, müssen einen nicht konstanten Namen verwenden.
Für Konstanten, die skalare Werte sind, muss der const-Modifikator verwendet werden.
Nicht konstante Namen
Nicht konstante Namen werden in CamelCase geschrieben. Sie gelten für Instanzeigenschaften, lokale Eigenschaften und Parameternamen.
val variable = "var" val nonConstScalar = "non-const" val mutableCollection: MutableSet<String> = 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 Wortgruppen mit Substantiven.
Sicherungsattribute
Wenn eine Backing Property erforderlich ist, sollte ihr Name genau mit dem der tatsächlichen Property übereinstimmen, nur mit einem Unterstrich als Präfix.
private var _table: Map<String, Int>? = null val table: Map<String, Int> get() { if (_table == null) { _table = HashMap() } return _table ?: throw AssertionError() }
Variablennamen eingeben
Jede Typvariable wird in einem von zwei Stilen benannt:
- Ein einzelner Großbuchstabe, optional gefolgt von einer einzelnen Ziffer (z. B.
E,T,X,T2) - Ein Name in der Form, die für Klassen verwendet wird, gefolgt vom Großbuchstaben
T(z. B.RequestT,FooBarT)
Camel-Case-Schreibweise
Manchmal gibt es mehr als eine sinnvolle Möglichkeit, einen englischen Begriff in CamelCase zu konvertieren, z. B. wenn Akronyme oder ungewöhnliche Konstrukte wie „IPv6“ oder „iOS“ vorhanden sind. Verwenden Sie das folgende Schema, um die Vorhersagbarkeit zu verbessern.
Beginnen Sie mit der Prosaform des Namens:
- Wandeln Sie den Begriff in reines ASCII um und entfernen Sie alle Apostrophe. Beispiel: „Müller’s algorithm“ wird zu „Muellers algorithm“.
- Teilen Sie dieses Ergebnis in Wörter auf, indem Sie es an Leerzeichen und verbleibenden Satzzeichen (in der Regel Bindestrichen) aufteilen. Empfohlen:Wenn ein Wort bereits im allgemeinen Sprachgebrauch in der Kamel-Schreibweise verwendet wird, teilen Sie es in seine Bestandteile auf (z. B. „AdWords“ wird zu „ad words“). Ein Wort wie „iOS“ ist an sich nicht in der Kamel-Schreibweise, sondern widerspricht jeder Konvention. Diese Empfehlung gilt daher nicht.
- Schreiben Sie alles klein (auch Akronyme) und führen Sie dann einen der folgenden Schritte aus:
- Der erste Buchstabe jedes Worts wird großgeschrieben, um Pascal-Case zu erhalten.
- Der erste Buchstabe jedes Worts mit Ausnahme des ersten wird großgeschrieben, um CamelCase zu erhalten.
- Fügen Sie schließlich alle Wörter zu einer einzigen ID zusammen.
Die Groß- und Kleinschreibung der Originalwörter wird fast vollständig ignoriert.
| Prosaform | Richtig | Falsch |
|---|---|---|
| „XML Http Request“ | XmlHttpRequest |
XMLHTTPRequest |
| „Neue Kunden-ID“ | newCustomerId |
newCustomerID |
| „inner stopwatch“ | innerStopwatch |
innerStopWatch |
| „Unterstützt IPv6 unter iOS“ | supportsIpv6OnIos |
supportsIPv6OnIOS |
| „YouTube-Importtool“ | YouTubeImporter |
YoutubeImporter* |
(* Akzeptabel, aber nicht empfohlen)
Dokumentation
Formatierung
Die grundlegende Formatierung von KDoc-Blöcken ist in diesem Beispiel zu sehen:
/** * 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. */
Die Grundform ist immer akzeptabel. Die einzeilige Form kann verwendet werden, wenn der gesamte KDoc-Block (einschließlich der Kommentarzeichen) in eine einzelne Zeile passt. Dies gilt nur, wenn keine Block-Tags wie @return vorhanden sind.
Absätze
Zwischen Absätzen und vor der Gruppe von Block-Tags (falls vorhanden) wird eine leere Zeile eingefügt, d. h. eine Zeile, die nur das ausgerichtete führende Sternchen (*) enthält.
Tags blockieren
Alle verwendeten Standard-Block-Tags werden in der Reihenfolge @constructor, @receiver, @param, @property, @return, @throws, @see angezeigt und haben immer eine Beschreibung.
Wenn ein Block-Tag nicht in eine einzelne Zeile passt, werden Fortsetzungszeilen um vier Leerzeichen von der Position des @ eingerückt.
Zusammenfassungsfragment
Jeder KDoc-Block beginnt mit einem kurzen Zusammenfassungsfragment. Dieses Fragment ist sehr wichtig, da es der einzige Teil des Texts ist, der in bestimmten Kontexten wie Klassen- und Methodenindexen angezeigt wird.
Das ist ein Fragment – eine Nominal- oder Verbalphrase, kein vollständiger Satz.
Es beginnt nicht mit „A `Foo` is a...“ oder „This method returns...“ und muss auch keinen vollständigen Imperativsatz wie „Save the record.“ bilden. Das Fragment wird jedoch großgeschrieben und mit Satzzeichen versehen, als wäre es ein vollständiger Satz.
Nutzung
KDoc ist mindestens für jeden public-Typ und jedes public- oder protected-Element eines solchen Typs vorhanden. Es gibt jedoch einige Ausnahmen, die unten aufgeführt sind.
Ausnahme: Selbsterklärende Funktionen
KDoc ist für „einfache, offensichtliche“ Funktionen wie getFoo und Attribute wie foo optional, wenn es wirklich nichts anderes zu sagen gibt als „Gibt den Foo zurück“.
Es ist nicht angemessen, diese Ausnahme anzuführen, um das Weglassen relevanter Informationen zu rechtfertigen, die ein typischer Leser möglicherweise wissen muss. Wenn Sie beispielsweise eine Funktion mit dem Namen getCanonicalName oder eine Eigenschaft mit dem Namen canonicalName dokumentieren, lassen Sie die Dokumentation nicht weg, weil sie nur /** Returns the canonical name. */ enthalten würde. Ein typischer Leser hat möglicherweise keine Ahnung, was der Begriff „kanonischer Name“ bedeutet.
Ausnahme: Überschreibungen
KDoc ist nicht immer für eine Methode vorhanden, die eine Methode des Supertyps überschreibt.