Przewodnik stylistyczny Kotlin

Ten dokument stanowi pełną definicję standardów Google dotyczących kodowania Androida w przypadku kodu źródłowego w języku programowania Kotlin. Plik źródłowy Kotlin jest opisany jako w stylu Google Android Style tylko pod warunkiem, że jest zgodny z niniejszymi zasadami.

Podobnie jak w przypadku innych przewodników dotyczących stylu programowania, poruszane tu problemy obejmują nie tylko problemy estetyczne z formatowaniem, ale także inne rodzaje konwencji i standardów kodowania. W tym dokumencie skupiamy się jednak głównie na sztywnych i szybkich zasadach, których przestrzegamy powszechnie, i nie udziela porad, których nie można wyegzekwować przez człowieka lub przy użyciu narzędzi.

Ostatnia aktualizacja: 6 września 2023 r.

Pliki źródłowe

Wszystkie pliki źródłowe muszą mieć kodowanie UTF-8.

Nazewnictwo

Jeśli plik źródłowy zawiera tylko jedną klasę najwyższego poziomu, nazwa pliku powinna zawierać nazwę z uwzględnieniem wielkości liter oraz rozszerzenie .kt. W przeciwnym razie jeśli plik źródłowy zawiera wiele deklaracji najwyższego poziomu, wybierz nazwę który opisuje zawartość pliku, zastosuj PascalCase (camelCase to jest dopuszczalne, jeśli nazwa pliku zawiera liczbę mnogą) i dołączaj rozszerzenie .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() = // …

Znaki specjalne

Znaki odstępów

Oprócz sekwencji zakończenia wiersza funkcja Odstęp ASCII w poziomie (0 x 20) to jedyny znak odstępu występujący w dowolnym miejscu pliku źródłowego. Oznacza to, że:

  • Wszystkie pozostałe znaki odstępu w ciągach znaków i literałach znaków podlegają zmianie znaczenia.
  • Znaki tabulacji nie służą do wcięć.

Specjalne sekwencje zmiany znaczenia

Dotyczy dowolnych znaków ze specjalną sekwencją zmiany znaczenia. (\b, \n, \r, \t, \', \", \\ i \$), używana jest ta sekwencja zamiast odpowiadającego jej Unicode. (np. \u000a).

Znaki spoza zestawu ASCII

W przypadku pozostałych znaków spoza zestawu ASCII jest to rzeczywisty znak Unicode. (np. ) lub równoważny kod zmiany znaczenia Unicode (np. \u221e). Wybór zależy tylko od tego, który kod łatwiej je przeczytać i zrozumieć. Nie zalecamy zmiany znaczenia znaków w kodzie Unicode w przypadku znaków, które można wydrukować w dowolnym miejscu. są zdecydowanie odradzane poza literałami łańcuchowymi i komentarzami.

Przykład Dyskusja
val unitAbbrev = "μs" Najlepsza: jasne, nawet bez komentarza.
val unitAbbrev = "\u03bcs" // μs Kiepsko: nie ma powodu, by używać znaków ucieczki z postacią do wydrukowania.
val unitAbbrev = "\u03bcs" Kiepsko: czytelnik nie ma pojęcia, co to jest.
return "\ufeff" + content Dobra: w przypadku znaków niedrukowalnych użyj zmiany znaczenia, a w razie potrzeby dodaj komentarz.

Struktura

Plik .kt zawiera w kolejności:

  • Nagłówek dotyczący praw autorskich lub licencji (opcjonalnie)
  • Adnotacje na poziomie pliku
  • Instrukcje dotyczące pakietu
  • Importuj instrukcje
  • Deklaracje najwyższego poziomu

Każdą z tych sekcji rozdziela dokładnie 1 pusty wiersz.

Jeśli w pliku znajduje się nagłówek dotyczący praw autorskich lub licencji, umieść go na samej górze w wielowierszowym komentarzu.

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

Nie używaj stylu KDoc. lub jednowierszowy komentarz.

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

Adnotacje na poziomie pliku

Adnotacje z plikiem „file” własna witryna docelowa są umieszczane między komentarzem nagłówka a deklaracją pakietu.

Instrukcje dotyczące pakietu

Instrukcje dotyczące pakietu nie podlegają żadnym limitom kolumn i nigdy nie są zawijane do wierszy.

Importuj instrukcje

Instrukcje importu dla klas, funkcji i właściwości są zgrupowane na jednej liście i sortowane według znaków ASCII.

Importy z użyciem symboli wieloznacznych (jakiegokolwiek typu) są niedozwolone.

Podobnie jak w przypadku deklaracji dotyczącej pakietu, instrukcje importu nie podlegają i nigdy nie są zawijane wierszy.

Deklaracje najwyższego poziomu

Plik .kt może zadeklarować co najmniej 1 typ, funkcję, właściwości lub typ na najwyższym poziomie.

Zawartość pliku powinna dotyczyć pojedynczego motywu. Przykłady byłby jednym typem publicznym lub zbiorem funkcji rozszerzeń wykonujących tę samą operację na różnych typach odbiorników. Niepowiązane deklaracje powinny być oddzielone na własne pliki i publiczne deklaracje w jednym pliku powinno zostać zminimalizowane.

Nie nakładamy żadnych wyraźnych ograniczeń na liczbę ani kolejność treści plik.

Pliki źródłowe są zwykle odczytywane od góry do dołu, co oznacza, że w kolejności ogólne, powinno odzwierciedlać, że deklaracje wyżej będą informować co dzieje się dalej. Różne pliki mogą się zdecydować na zamówienie ich treść w różny sposób. Podobnie 1 plik może zawierać 100 właściwości, kolejne 10 funkcji i kolejną jedną klasę.

Ważne jest, aby każdy plik był w określonej kolejności logicznej, opiekun klienta może wyjaśnić, jeśli zostanie o to poproszony. Na przykład nowe funkcje to nie tylko są regularnie dodawane na końcu pliku, co zapewnia „chronologiczną” według daty dodania”, która nie jest logiczna.

Sortowanie uczestników zajęć

Kolejność uczestników zajęć jest zgodna z tymi samymi regułami co w przypadku klasy najwyższego poziomu deklaracje.

Formatowanie

Aparaty ortodontyczne

Nawiasy nie są wymagane w przypadku gałęzi when i wyrażeń if które mają nie więcej niż jedną gałęzie else i mieszczą się w jednej linii.

if (string.isEmpty()) return

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

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

Nawiasy klamrowe są wymagane w przypadku każdej gałęzi if, for, when, do, i while instrukcji i wyrażeń, nawet jeśli treść jest pusta lub zawiera tylko pojedyncza instrukcja.

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

Niepuste bloki

Aparaty są zgodne ze stylem Kernighan i Ritchie („nawiasy egipskie”), w których niepuste bloki i konstrukcje blokowe:

  • Brak podziału wiersza przed nawiasem otwierającym.
  • Podział wiersza po otwierającym nawiasie klamrowym.
  • Podział wiersza przed zamykającym nawiasem klamrowym.
  • Podział wiersza po zamykającym nawiasie klamrowym tylko wtedy, gdy dany nawias zamyka nawias klamrowy. lub kończy treść funkcji, konstruktora lub klasy nazwanej. Na przykład: nie ma podziału wiersza po nawiasie klamrowym, po którym następuje znak else lub przecinek.
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()
        }
    }
}

Kilka wyjątków dla: klasy wyliczeniowe podane niżej.

Puste bloki

Pusty blok lub konstrukcja blokowa musi być w stylu K&R.

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

Wyrażenia

Warunek if/else używany jako wyrażenie może pomijaj nawiasy klamrowe tylko wtedy, gdy całe wyrażenie mieści się w jednym wierszu.

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
}

Wcięcie

Przy każdym otwarciu nowej bryły lub konstrukcji bryłowej wcięcie zwiększa się o cztery spacje. Po zakończeniu bryły wcięcie wróci do poprzedniego poziomu wcięcia. Poziom wcięcia odnosi się zarówno do kodu, jak i komentarzy w całym bloku.

Jedna instrukcja w wierszu

Po każdej instrukcji znajduje się znak podziału wiersza. Średniki nie są używane.

Zawijanie wierszy

Kod może zawierać maksymalnie 100 znaków w kolumnach. Z wyjątkiem przypadków opisanych poniżej każdy wiersz, który przekraczałby ten limit, musi być zawijany w sposób opisany poniżej.

Wyjątki:

  • Wiersze, przy których przestrzeganie limitu kolumn jest niemożliwe (na przykład długi adres URL w pliku KDoc)
  • Wyciągi package i import
  • Wiersze poleceń w komentarzu, które można wyciąć i wkleić do powłoki

Gdzie zrobić przerwę

Najważniejsza dyrektywa w zakresie zawijania wierszy to: preferować podział na wyższym poziomie składni. Poza tym:

  • Jeśli wiersz jest zerwany w operatorze lub nazwie funkcji przyrostowej, po nazwie operatora lub funkcji przyrostowej.
  • Jeśli linia jest łamana obok następujących symboli podobnych do operatorów, podział znajduje się przed symbolem:
    • Separator kropek (., ?.).
    • Dwa dwukropki odniesienia do członka (::).
  • Nazwa metody lub konstruktora pozostaje dołączona do otwartego nawiasu ((), który zgodnie z nim.
  • Przecinek (,) pozostaje dołączony do poprzedzającego go tokena.
  • Strzałka lambda (->) pozostaje dołączona do poprzedzającej ją listy argumentów.
.

Funkcje

Jeśli podpis funkcji nie mieści się w jednym wierszu, rozdziel każdą deklarację parametrów do osobnego wiersza. Parametry zdefiniowane w tym formacie powinny mieć pojedyncze wcięcie (+4). Nawias zamykający ()) i typ zwracany są umieszczone w osobnym wierszu bez dodatkowego wcięcia.

fun <T> Iterable<T>.joinToString(
    separator: CharSequence = ", ",
    prefix: CharSequence = "",
    postfix: CharSequence = ""
): String {
    // …
}
Funkcje wyrażeń

Jeśli funkcja zawiera tylko jedno wyrażenie, może zostać przedstawiona jako funkcji wyrażenia.

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

Właściwości

Gdy inicjator właściwości nie mieści się w jednym wierszu, poprzedź znak równości (=) i użyj wcięcia.

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

Właściwości deklarujące funkcję get lub set powinny umieszczać każdą z nich na własny wiersz ze zwykłym wcięciem (+4). Sformatuj je przy użyciu tych samych reguł .

var directory: File? = null
    set(value) {
        // …
    }
Usługi tylko do odczytu mogą używać krótszej składni, która mieści się w jednym wierszu.
val defaultExtension: String get() = "kt"

Odstęp

Branża

Pojawi się jeden pusty wiersz:

  • Między kolejnymi elementami klasy: właściwości, konstruktory, funkcje, klasy zagnieżdżone itp.
    • Wyjątek: pusty wiersz między dwiema wartościami. następujące po sobie właściwości (bez innego kodu między nimi) jest opcjonalna. Takie puste wiersze są używane w razie potrzeby do utworzenia logiczne grupy usług i ich powiązanie z właściwą bazą danych, jeśli istnieje.
    • Wyjątek: ukryte są puste linie między stałymi wyliczeniami. poniżej.
  • Pomiędzy instrukcjami w razie potrzeby w celu uporządkowania kodu na logiczne podsekcje.
  • Opcjonalnie przed pierwszą instrukcją w funkcji przed pierwszym członkiem zajęć lub po ostatnim członkowi zajęć zajęcia (nie zachęca się ani nie zniechęca).
  • Zgodnie z wymogami innych sekcji tego dokumentu (np. Struktura).

Dozwolone jest wiele następujących po sobie pustych wierszy, ale nie jest to zalecane. kiedykolwiek wymagane.

Pozioma

Oprócz tego, że wymagają tego ustawienia języka lub innych reguł stylu, oraz literał, komentarze i dokument KDoc, pojedynczy kod ASCII spacja pojawia się również tylko w następujących miejscach:

  • Oddzielając dowolne zastrzeżone słowo, np. if, for lub catch z nawiasu otwierającego ((), który następuje po nim w tym wierszu.
    // WRONG!
    for(i in 0..1) {
    }
    
    // Okay
    for (i in 0..1) {
    }
    
  • Oddzielenie dowolnego zastrzeżonego słowa, np. else lub catch, z zamykający nawias klamrowy (}), który poprzedza go w tej linii.
    // WRONG!
    }else {
    }
    
    // Okay
    } else {
    }
    
  • Przed dowolnym otwartym nawiasem klamrowym ({).
    // WRONG!
    if (list.isEmpty()){
    }
    
    // Okay
    if (list.isEmpty()) {
    }
    
  • Po obu stronach dowolnego operatora binarnego.
    // WRONG!
    val two = 1+1
    
    // Okay
    val two = 1 + 1
    
    Dotyczy to również tych symboli podobnych do operatorów:
    • strzałka w wyrażeniu lambda (->).
      // WRONG!
      ints.map { value->value.toString() }
      
      // Okay
      ints.map { value -> value.toString() }
      
    . Nie:
    • dwukropki (::) odwołania do elementu członkowskiego.
      // WRONG!
      val toString = Any :: toString
      
      // Okay
      val toString = Any::toString
      
    • separatorem kropek (.).
      // WRONG
      it . toString()
      
      // Okay
      it.toString()
      
    • operator zakresu (..).
      // WRONG
      for (i in 1 .. 4) {
        print(i)
      }
      
      // Okay
      for (i in 1..4) {
        print(i)
      }
      
  • Przed dwukropkiem (:) tylko wtedy, gdy jest używany w deklaracji klasy do określenia klasę bazową lub interfejsy bądź jej użycie w klauzuli where. w przypadku ogólnych ograniczeń.
    // 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>
    
  • Po przecinku (,) lub dwukropku (:).
    // WRONG!
    val oneAndTwo = listOf(1,2)
    
    // Okay
    val oneAndTwo = listOf(1, 2)
    
    // WRONG!
    class Foo :Runnable
    
    // Okay
    class Foo : Runnable
    
  • Po obu stronach ukośnika podwójnego (//), który zaczyna się na końcu wiersza. W tym przypadku można wpisać wiele spacji, ale nie jest to wymagane.
    // WRONG!
    var debugging = false//disabled by default
    
    // Okay
    var debugging = false // disabled by default
    

Ta reguła nigdy nie jest interpretowana jako wymagająca lub zabroniona dodatkowe miejsce na początku lub na końcu wiersza; dotyczy tylko do wewnątrz.

Konkretne konstrukcje

Klasy typu wyliczeniowego

Wyliczenie bez funkcji i bez dokumentacji stałych można opcjonalnie sformatować jako pojedynczy wiersz.

enum class Answer { YES, NO, MAYBE }

Gdy stałe w wygenerowaniu znajdują się w osobnych wierszach, nie muszą one oddzielać pustych wierszy. Wyjątkiem są sytuacje, gdy definiują treść.

enum class Answer {
    YES,
    NO,

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

Klasy typu wyliczeniowego są klasami, więc obowiązują wszystkie inne reguły formatowania.

Adnotacje

Adnotacje członka lub typu są umieszczane w osobnych wierszach bezpośrednio przed konstrukcją z adnotacjami.

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

Adnotacje bez argumentów można umieszczać w jednym wierszu.

@JvmField @Volatile
var disposable: Disposable? = null

Gdy istnieje tylko jedna adnotacja bez argumentów, można umieścić w tym samym wierszu co deklaracja.

@Volatile var disposable: Disposable? = null

@Test fun selectAll() {
    // …
}

Składni @[...] można używać tylko z jawnym miejscem docelowym w witrynie i tylko w przypadku: przez połączenie co najmniej 2 adnotacji bez argumentów w jednym wierszu.

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

Pośredni zwrot/typy usług

Jeśli treść funkcji wyrażenia lub inicjator właściwości jest wartością skalarną lub typ zwracanego towaru można łatwo wywnioskować z treści, a następnie można pominąć.

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

Pisząc bibliotekę, zachowaj deklarację typu jawnego, gdy jest częścią publicznego interfejsu API.

Nazewnictwo

Identyfikatory zawierają tylko litery i cyfry z zestawu ASCII oraz, w niewielkiej liczbie przypadków wymienionych poniżej, podkreślenia. W ten sposób każda prawidłowa nazwa identyfikatora jest dopasowywana do wyrażenia regularnego \w+.

prefiksy specjalne (np. te występujące w przykładach); name_, mName, s_name i kName nie są używane z wyjątkiem tych właściwości kopii zapasowej (zobacz Właściwości kopii zapasowej).

Nazwy pakietów

Nazwy pakietów są zapisane małymi literami, zawierają po prostu kolejne słowa połączone razem (bez znaków podkreślenia).

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

Wpisz nazwy

Nazwy klas są pisane w zapisie PascalCase i zazwyczaj są rzeczownikami lub rzeczownikami wyrażeniami. na przykład Character lub ImmutableList. Nazwy interfejsów mogą mogą to być również rzeczowniki lub wyrażenia rzeczowniki (np. List), ale mogą to być czasami przymiotniki lub wyrażenia przymiotnikowe (na przykład Readable).

nazwy klas testowych zaczynają się od nazwy klasy, którą testują; z końcówką Test. Na przykład HashTest lub HashIntegrationTest

Nazwy funkcji

Nazwy funkcji zapisuje się wielkimi literami w przypadku znaków wielbłąda. Zwykle są to czasowniki lub wyrażenia. na przykład sendMessage lub stop.

W nazwach funkcji testowych mogą być używane podkreślenia, aby rozdzielić logiczne komponenty nazwy.

@Test fun pop_emptyStack() {
    // …
}

Funkcje z adnotacjami @Composable, które zwracają wartość Unit, są typu PascalCased i nazwane jak rzeczowniki, tak jakby były typami.

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

Nazwy funkcji nie powinny zawierać spacji, ponieważ nie w każdym (na szczególną uwagę zasługuje funkcja, która nie jest w pełni obsługiwana w systemie Android).

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

Stałe nazwy

W nazwach stałych używane są znaki UPPER_SNAKE_CASE: wszystkie wielkie litery, ze słowami rozdzielonymi podkreśleniami. Czym dokładnie jest stała?

Stałe to właściwości val bez niestandardowej funkcji get, których zawartość to których nie można zmienić, a jego funkcje nie mają żadnych wykrywalnych skutków ubocznych. Ten obejmuje typy stałe i stałe zbiory typów stałych a także skalary i ciąg znaków, jeśli zostały oznaczone jako const. Jeśli dowolna z instancji ale nie jest stałą wartością. Zamierzam wyłącznie To za mało.

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

Nazwy te są zwykle rzeczownikami lub wyrażeniami rzeczownikami.

Wartości stałe można zdefiniować tylko wewnątrz elementu object lub jako deklarację najwyższego poziomu. Wartości, które w przeciwnym razie spełniają wymagania stała, ale zdefiniowana wewnątrz elementu class, musi mieć nazwę niestałą.

Stałe, które są wartościami skalarnymi, muszą używać funkcji const modyfikatorze.

Nazwy niestałe

Nazwy niestałe zapisuje się wielkimi literami wielka litera. Dotyczą one właściwości instancji, właściwości lokalnych i nazw parametrów.

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

Nazwy te są zwykle rzeczownikami lub wyrażeniami rzeczownikami.

Właściwości kopii zapasowej

Gdy usługa pomocnicza jest wymagana, jej nazwa powinna być dokładnie taka sama jak nazwa nieruchomości oprócz tych, które są poprzedzone znakiem podkreślenia.

private var _table: Map? = null

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

Wpisz nazwy zmiennych

Każda zmienna typu ma nazwę w jednym z 2 sposobów:

  • pojedyncza wielka litera, po której może następować znak jedna cyfra (np. E, T, X, T2)
  • Imię i nazwisko w formie użytej do oznaczenia zajęć z dopiskiem wielką literą litera T (np. RequestT, FooBarT)

Wielbłąd wielkanocny

Czasami istnieje kilka rozsądnych sposobów zamiany angielskich wyrażeń na wielbłądy, na przykład przez akronimy lub nietypowe konstrukcje, takie jak „IPv6” lub „iOS”. Aby zwiększyć przewidywalność, użyj poniższego schematu.

Zacznijmy od formy prosowej imienia i nazwiska:

  1. Zmień wyrażenie na zwykłe ASCII i usuń wszelkie apostrofy. Na przykład „algorytm Mullera” może zostać zastąpiony przez „algorytm Mullera”.
  2. Podziel wynik na słowa, rozdzielając je spacjami i pozostałymi znakami interpunkcyjnymi (zwykle łącznikami). Zalecane: jeśli jakieś słowo ma już powszechny wygląd wielbłąda, podziel je na części składowe (np. „AdWords” stanie się „słowami reklamowymi”). Zwróć uwagę, że słowo takie jak „iOS” nie jest pisane jak wielka litera, jest sprzeczne z każdą konwencją, więc nie ma zastosowania.
  3. Teraz wszystko jest zapisane małymi literami (w tym akronimy), a potem wykonaj jedną z tych czynności:
    • Pierwszy znak każdego wyrazu należy pisać wielką literą, aby uzyskać wielkość liter jak w przypadku poszczególnych słów.
    • Wielkie litery w każdym słowie z wyjątkiem pierwszego znaku wielbłąda.
  4. Na koniec połącz wszystkie słowa w jeden identyfikator.

Zwróć uwagę, że wielkość liter w oryginalnych słowach jest niemal całkowicie ignorowana.

Formularz prose Dobrze Nieprawidłowo
„Żądanie XML HTTP” XmlHttpRequest XMLHTTPRequest
„nowy identyfikator klienta” newCustomerId newCustomerID
"wewnętrzny stoper" innerStopwatch innerStopWatch
„obsługuje IPv6 w iOS” supportsIpv6OnIos supportsIPv6OnIOS
„Importer YouTube” YouTubeImporter YoutubeImporter*

(* Dopuszczalne, ale niezalecane).

Dokumentacja

Formatowanie

Podstawowe formatowanie bloków KDoc przedstawiono w tym przykładzie:

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

...lub w tym przykładzie z jednym wierszem:

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

Zawsze akceptowalna jest forma podstawowa. Format jednowierszowy może być podmieniane, gdy cały blok KDoc (łącznie ze znacznikami komentarzy) nie zmieści się w jednej linii. Należy pamiętać, że ma to zastosowanie tylko wówczas, gdy nie są zdefiniowane żadne wartości blokuj tagi, takie jak @return.

Akapity

jeden pusty wiersz, czyli wiersz zawierający tylko wyrównaną na początku gwiazdkę. (*) – pojawia się między akapitami i przed grupą tagów blokujących, jeśli występuje.

Blokuj tagi

Wszystkie używane standardowe „tagi blokowe” pojawiają się w określonej kolejności. @constructor, @receiver, @param, @property, @return @throws, @see i nigdy nie pojawiają się bez pustego opisu. Jeśli tag blokowy nie mieści się w jednej linii, są dodane wcięcie o 4 spacje od pozycji @.

Fragment podsumowania

Każdy blok KDoc zaczyna się od krótkiego fragmentu podsumowania. Ten fragment jest bardzo ważne: jest to jedyna część tekstu, która pojawia się w określonych kontekstach, takich jak indeksy klas i metod.

Jest to fragment – wyrażenie rzeczownikowe lub wyrażenie czasownik, a nie całe zdanie. Nie zaczyna się od „A `Foo` is a...”, lub „This method returns...”, nie musi też stanowić pełnego zdania imperatywnego, „Save the record.”. Jest on jednak pisany wielkimi literami, przekreślone, jakby to było pełne zdanie.

Wykorzystanie

KDoc istnieje przynajmniej dla każdego typu public, a każdy element public lub protected tego typu, z kilkoma wyjątkami opisanymi poniżej.

Wyjątek: funkcje wyjaśniające

Narzędzie KDoc jest opcjonalne w przypadku funkcji „prostych, oczywistych”, takich jak getFoo i właściwości takich jak foo.

Nie ma sensu cytować tego wyjątku, aby uzasadnić pominięcie stosownych przydatne dla przeciętnego czytelnika. Na przykład w przypadku funkcji funkcję o nazwie getCanonicalName lub właściwości o nazwie canonicalName, nie pomijać dokumentacji (pod warunkiem, że doszło do /** Returns the canonical name. */), jeśli typowy czytnik może nie mieć co to jest „nazwa kanoniczna” co znaczy!

Wyjątek: zastąpienia

Wartość KDoc nie zawsze jest dostępna w metodzie, która zastępuje metodę typu supertyp.