המסמך הזה משמש כהגדרה המלאה של תקני התכנות של Google ב-Android עבור קוד המקור בשפת התכנות Kotlin. קובץ מקור של Kotlin מתואר כקובץ בסגנון Google Android, אם הוא עומד בכללים המפורטים כאן בלבד.
כמו מדריכים אחרים לסגנונות תכנות, הנושאים שנלמדים כוללים לא רק נושאים אסתטיים של עיצוב, אלא גם סוגים אחרים של מוסכמות או תקני תכנות. עם זאת, המסמך מתמקד בעיקר בכללים הקשים והמהירים שעל פינו פועלים לפיהם, ומונע מתן עצות שאינן ניתנות לאכיפה באופן ברור (על ידי בני אדם או כלי).
קובצי מקור
כל קובצי המקור חייבים להיות מקודדים לפי UTF-8.
מתן שמות
אם קובץ מקור מכיל רק מחלקה אחת ברמה העליונה, שם הקובץ
צריך לשקף את השם תלוי אותיות רישיות והתוסף .kt
. אחרת,
אם קובץ מקור מכיל כמה הצהרות ברמה העליונה, צריך לבחור שם
שמתאר את תוכן הקובץ, החל את PascalCase (camelCase היא
קביל אם שם הקובץ הוא רבים), ומצרפים את הסיומת .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() = // …
תווים מיוחדים
תווי רווח לבן
חוץ מרצף של מסיים הקו, תו רווח אופקי ב-ASCII (0x20) הוא תו הרווח הלבן היחיד שמופיע במקום כלשהו בקובץ המקור. כלומר:
- כל שאר תווי הרווחים הלבנים בליטרל של מחרוזות ובמילים של תווים מסומנים בתו בריחה.
- תווי Tab לא משמשים לכניסת פסקה.
רצפי בריחה מיוחדים
לכל תו שיש לו רצף בריחה מיוחד
(\b
, \n
, \r
, \t
, \'
, \"
, \\
וגם \$
),
צריך להשתמש ברצף ולא ב-Unicode התואם
(למשל \u000a
) Escape.
תווים שאינם ASCII
בשאר התווים שאינם ASCII, תו ה-Unicode בפועל
(למשל ∞
) או בתו בריחה המקביל ב-Unicode (למשל, \u221e
).
הבחירה תלויה רק בגורם שהקוד
קל יותר לקרוא ולהבין.
לא מומלץ להשתמש בתו בריחה (escape) בפורמט Unicode עבור תווים שניתן להדפיס בכל מיקום
מומלץ מאוד להימנע משימוש במחרוזת ולא בתגובות.
דוגמה | דיון |
---|---|
val unitAbbrev = "μs" |
הכי טוב: ברור לגמרי גם בלי תגובה. |
val unitAbbrev = "\u03bcs" // μs |
גרוע: אין סיבה להשתמש בתו בריחה (escape) עם דמות שניתן להדפיס. |
val unitAbbrev = "\u03bcs" |
גרוע: לקורא אין שום מושג על מה הבעיה. |
return "\ufeff" + content |
אפשרות טובה: יש להשתמש בתו בריחה (escape) עבור תווים שאינם ניתנים להדפסה, ובמקרה הצורך להוסיף הערה. |
מבנה
קובץ .kt
מורכב מהפרטים הבאים, לפי הסדר:
- כותרת זכויות יוצרים ו/או רישיון (אופציונלי)
- הערות ברמת הקובץ
- דוח החבילה
- ייבוא דפי חשבון
- הצהרות ברמה העליונה
שורה ריקה אחת בדיוק מפרידה בין כל הקטעים.
זכויות יוצרים / רישיון
אם לקובץ יש כותרת של זכויות יוצרים או רישיון, יש למקם אותה בראש הדף באופן מיידי בתגובה לכמה שורות.
/* * Copyright 2017 Google, Inc. * * ... */
אין להשתמש בסגנון KDoc או תגובה בסגנון שורה אחת.
/** * Copyright 2017 Google, Inc. * * ... */
// Copyright 2017 Google, Inc. // // ...
הערות ברמת הקובץ
הערות עם ה'קובץ' שימוש בטירגוט לפי אתר מוצבות בין כל תגובה לכותרת לבין הצהרת החבילה.
דוח החבילה
הצהרת החבילה לא כפופה למגבלת עמודות כלשהי ואף פעם לא מוקפת בשורה.
ייבוא דפי חשבון
הצהרות ייבוא של מחלקות, פונקציות ומאפיינים מקובצים יחד ברשימה אחת ומיון ASCII.
אסור לייבא תווים כלליים לחיפוש (מכל סוג).
בדומה להצהרת החבילה, הצהרות הייבוא לא כפופות ל העמודות המקסימליות, והן אף פעם לא מוקפות בשורה.
הצהרות ברמה העליונה
קובץ .kt
יכול להצהיר על סוג, פונקציות, מאפיינים או סוג אחד או יותר
חלופיים ברמה העליונה.
התוכן של קובץ צריך להתמקד בנושא אחד. דוגמאות לכך הוא סוג ציבורי יחיד או קבוצה של פונקציות תוסף שמבצעות את פעולה זהה במספר סוגי מקלטים. הצהרות לא קשורות צריכות להיות מופרדים לקבצים שלהם ולהצהרות ציבוריות בתוך קובץ יחיד צריך למזער אותו.
לא חלה הגבלה מפורשת על מספר התכנים או על הסדר שלהם קובץ.
בדרך כלל קוראים קובצי מקור מלמעלה למטה, כלומר ההזמנה, באופן כללי, צריכה לשקף שההצהרות בדרגה גבוהה יותר יודיעו להבנה של אלה שנמצאים רחוק יותר. אפשר להזמין קבצים שונים את התוכן שלהם בצורה שונה. באופן דומה, קובץ אחד יכול להכיל 100 מאפיינים, ועוד 10 פונקציות, ועוד מחלקה אחת.
מה שחשוב הוא שבכל קובץ ייעשה שימוש בסדר לוגי כלשהו, שמנהל התחזוקה יוכל להסביר זאת אם הוא יבקש ממנו. לדוגמה, פונקציות חדשות לא נוסף בדרך כלל לסוף הקובץ, כי כך תקבלו "כרונולוגיות" לפי תאריך הוספה', שהיא לא סדר לוגי.
הזמנת חברים בכיתה
הסדר של חברי הכיתה בכיתה תואם לאותם כללים כמו ברמה העליונה וההצהרות שלו.
עיצוב
פלטה לשיניים
לא צריך סוגריים מסולסלים להסתעפויות when
ולהבעות if
שכוללים לא יותר מהסתעפות else
אחת שנכנסה לשורה אחת.
if (string.isEmpty()) return val result = if (string.isEmpty()) DEFAULT_VALUE else string when (value) { 0 -> return // … }
אחרת צריך להוסיף סוגריים מסולסלים לכל הסתעפות if
, for
, when
, do
,
ו-while
הצהרות וביטויים, גם כאשר הגוף ריק או מכיל רק
הצהרה אחת.
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) }
בלוקים לא ריקים
סוגריים מסולסלים תואמים לסגנון קרניתן וריצ'י ("סוגריים מצריים") בלוקים לא ריקים ומבנים דמויי בלוקים:
- אין מעבר שורה לפני הסוגריים הפותחים.
- מעבר שורה אחרי הסוגריים הפותחים.
- מעבר שורה לפני הסוגר הסוגר.
- מעבר שורה אחרי הסוגר הסוגר, רק אם הסוגר הזה מסיים
מציין או מסיים את הגוף של פונקציה, של constructor או של מחלקה בעל שם.
למשל, אין מעבר שורה אחרי הסוגר הסוגריים אם אחריו מופיע
else
או פסיק.
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() } } }
למעט כמה יוצאים מן הכלל מחלקות enum בהמשך מוסבר איך עושים את זה.
בלוקים ריקים
בלוק ריק או מבנה דמוי בלוק חייב להיות בסגנון K&R.
try { doSomething() } catch (e: Exception) {} // WRONG!
try { doSomething() } catch (e: Exception) { } // Okay
ביטויים
תנאי if/else
שמשמש כביטוי יכול
יש להשמיט סוגריים מסולסלים רק אם כל הביטוי מתאים לשורה אחת.
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 }
כניסת פסקה
בכל פעם שנפתח מבנה חדש הדומה לבלוק או לבלוק, ערך הכניסה גדל בארבעה רווחים. כשהבלוק מסתיים, כניסת הפיסקה חוזרת לרמת הכניסה הקודמת. רמת כניסת הפיסקה חלה גם על הקוד וגם על התגובות בכל הבלוק.
דוח אחד בכל שורה
אחרי כל הצהרה יש מעבר שורה. לא נעשה שימוש בנקודה ופסיק.
גלישת קו
מגבלת העמודות של הקוד היא 100 תווים. למעט כפי שמצוין בהמשך, כל שורה שתחרוג מהמגבלה הזו חייבת להיות מוקפת שורה, כפי שמוסבר בהמשך.
חריגים:
- קווים שבהם לא ניתן לעמוד בדרישות מגבלת העמודות (לדוגמה, כתובת URL ארוכה ב-KDoc)
- דוחות
package
ו-import
- את שורות הפקודה בתגובה שאפשר לגזור ולהדביק אותן במעטפת
איפה להפסיק
ההנחיה הראשונית של גלישת שורות היא: עדיף לשבור ברמה תחבירית גבוהה יותר. כמו כן:
- כשהשורה מתנתקת באופרטור או בשם של פונקציה, ההפסקה מופיעה אחרי האופרטור או אחרי שם הפונקציה.
- כאשר קו נשבר בסמלים הבאים "כמו אופרטור", הפסקה
מופיע לפני הסמל:
- מפריד הנקודות (
.
,?.
). - שני תווי הנקודתיים של קובץ עזר של חבר (
::
).
- מפריד הנקודות (
- שם שיטה או שם של constructor נשאר מוצמד לסוגריים הפתוחים (
(
) עוקב אחריה. - פסיק (
,
) נשאר מצורף לאסימון שלפניו. - חץ lambda (
->
) נשאר מצורף לרשימת הארגומנטים שמופיעה לפניה.
פונקציות
אם חתימת פונקציה לא מתאימה לשורה אחת, צריך לפצל כל הצהרת פרמטר בשורה נפרדת. לפרמטרים שמוגדרים בפורמט הזה צריך להשתמש בכניסת פיסקה אחת (4+). הסוגר הסוגר ()
) וסוג ההחזרה מוצבים בשורה נפרדת ללא כניסת פסקה נוספת.
fun <T> Iterable<T>.joinToString( separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "" ): String { // … }
פונקציות הבעה
כשפונקציה מכילה רק ביטוי אחד אפשר לייצג אותה בתור פונקציית הביטוי.
override fun toString(): String { return "Hey" }
override fun toString(): String = "Hey"
מאפיינים
אם מאתחל המאפיין לא מתאים לשורה אחת, צריך לשבור אחרי סימן השווה (=
) ולהשתמש בכניסת פסקה.
private val defaultCharset: Charset? = EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)
בנכסים שמצהירים על הפונקציה get
או set
צריך למקם כל אחד מהם
שורה משלהם עם כניסת פיסקה רגילה (+4). עיצוב המודעות לפי אותם כללים
בתור פונקציות.
var directory: File? = null set(value) { // … }בנכסים עם הרשאת קריאה בלבד אפשר להשתמש בתחביר קצר יותר שמתאים לשורה אחת.
val defaultExtension: String get() = "kt"
רווח לבן
אנכי
תופיע שורה ריקה אחת:
- בין חברים עוקבים במחלקה: נכסים, constructors,
פונקציות, מחלקות מקוננות וכו'.
- חריג: שורה ריקה בין שתי שורות נכסים עוקבים (ללא קוד אחר ביניהם) הוא אופציונלי. אפשר להשתמש בשורות ריקות כאלה לפי הצורך כדי ליצור קבוצות לוגיות של נכסים ומאפיינים משויכים בנכס הגיבוי שלהם, אם יש כזה.
- חריג: מכוסות שורות ריקות בין קבועי טיפוסים בני מנייה (enum) שלמטה.
- בין דפי חשבון, לפי הצורך כדי לארגן את הקוד לפרקי משנה לוגיים.
- אופציונלי לפני ההצהרה הראשונה בפונקציה, לפני החבר הראשון בכיתה, או אחרי החבר האחרון (לא מעודד ולא מומלץ).
- בהתאם לדרישות של חלקים אחרים במסמך הזה (כמו הקטע מבנה).
מותר להזין מספר שורות ריקות ברצף, אבל אסור אי פעם.
לרוחב
מעבר למה שנדרש על פי השפה או כללי סגנון אחרים, וחוץ מליטרלים, הערות ו-KDoc, גם במקומות הבאים בלבד:
- צריך להפריד מילים שמורות, כמו
if
,for
, אוcatch
בסוגריים פתוחים ((
) שמופיע אחריו בשורה הזו.// WRONG! for(i in 0..1) { }
// Okay for (i in 0..1) { }
- צריך להפריד מילה שמורה, כמו
else
אוcatch
, מתוך סוגר מסולסלים סוגר (}
) שקודם לו בקו הזה.// WRONG! }else { }
// Okay } else { }
-
לפני כל סוגריים מסולסלים פתוחים (
{
).// WRONG! if (list.isEmpty()){ }
// Okay if (list.isEmpty()) { }
-
משני הצדדים של אופרטור בינארי.
// WRONG! val two = 1+1
// Okay val two = 1 + 1
הדבר נכון גם לגבי הסמלים הבאים "כמו מפעיל":- החץ בביטוי lambda (
->
).// WRONG! ints.map { value->value.toString() }
// Okay ints.map { value -> value.toString() }
-
שני הנקודתיים (
::
) של אזכור חבר.// WRONG! val toString = Any :: toString
// Okay val toString = Any::toString
-
מפריד הנקודות (
.
).// WRONG it . toString()
// Okay it.toString()
-
אופרטור הטווח (
..
).// WRONG for (i in 1 .. 4) { print(i) }
// Okay for (i in 1..4) { print(i) }
- החץ בביטוי lambda (
-
לפני נקודתיים (
:
), רק אם נעשה בו שימוש בהצהרת הכיתה לציון מחלקה בסיסית או ממשקים, או כאשר נעשה בהם שימוש בסעיףwhere
עבור מגבלות כלליות.// 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>
-
אחרי פסיק (
,
) או נקודתיים (:
).// WRONG! val oneAndTwo = listOf(1,2)
// Okay val oneAndTwo = listOf(1, 2)
// WRONG! class Foo :Runnable
// Okay class Foo : Runnable
-
משני הצדדים של הקו הנטוי הכפול (
//
) שמתחיל תו תגובת סוף שורה. כאן מותר להשתמש במספר רווחים, אבל לא חובה.// WRONG! var debugging = false//disabled by default
// Okay var debugging = false // disabled by default
כלל זה אף פעם לא יפורש כדרישה או כמתן הצעות מחיר רווח נוסף בתחילת השורה או בסוף השורה; כתובות של החלל הפנימי.
מבנים ספציפיים
טיפוסים בני מנייה (enum)
טיפוס enum ללא פונקציות וללא תיעוד על הקבועים שלו יכול להיות בפורמט של שורה אחת.
enum class Answer { YES, NO, MAYBE }
אם קבועים בטיפוס טיפוסים ממוקמים בשורות נפרדות, לא צריך להוסיף ביניהם שורה ריקה, למעט במקרים שבהם הם מגדירים גוף.
enum class Answer { YES, NO, MAYBE { override fun toString() = """¯\_(ツ)_/¯""" } }
מכיוון שמחלקות enum הן מחלקות, כל שאר הכללים של מחלקות עיצוב חלים.
הערות
הערות של חבר או סוג ממוקמות בשורות נפרדות ממש לפני המבנה עם ההערות.
@Retention(SOURCE) @Target(FUNCTION, PROPERTY_SETTER, FIELD) annotation class Global
אפשר למקם הערות ללא ארגומנטים בשורה אחת.
@JvmField @Volatile var disposable: Disposable? = null
אם קיימת רק הערה אחת ללא ארגומנטים, אותה שורה עם ההצהרה.
@Volatile var disposable: Disposable? = null @Test fun selectAll() { // … }
ניתן להשתמש בתחביר @[...]
רק עם יעד מפורש של האתר, ורק עבור
שילוב של שתי הערות או יותר ללא ארגומנטים בשורה אחת.
@field:[JvmStatic Volatile] var disposable: Disposable? = null
החזרות משתמעות/סוגי נכס
אם גוף פונקציית ביטוי או מאתחל מאפיין הוא סקלר או את סוג ההחזרה ניתן להסיק בבירור מהגוף. ניתן להשמיט.
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")
כשכותבים ספרייה, צריך לשמור את הצהרת הסוג המפורשת כאשר הוא חלק מה-API הציבורי.
מתן שמות
המזהים משתמשים רק באותיות ובספרות ASCII, ובמספר קטן של מקרים הבאים, קווים תחתונים. לכן, כל שם מזהה חוקי תואם לביטוי הרגולרי \w+
.
קידומות או סיומות מיוחדות, כמו אלה שניתן לראות בדוגמאות
לא נעשה שימוש ב-name_
, ב-mName
, ב-s_name
וב-kName
למעט במקרה של
מאפייני גיבוי (ראו
גיבוי מאפיינים).
שמות החבילות
כל שמות החבילות מופיעים באותיות קטנות. באנגלית פשוט מזינים מילים ברצף. משורשרים יחד (ללא קווים תחתונים).
// Okay package com.example.deepspace // WRONG! package com.example.deepSpace // WRONG! package com.example.deep_space
שמות של סוגי תווים
שמות הכיתות נכתבים ב-PascalCase והם בדרך כלל שמות עצם או שמות עצם
וביטויים. לדוגמה, Character
או ImmutableList
. ייתכן ששמות הממשקים
להיות גם שמות עצם או ביטויים של שמות עצם (לדוגמה, List
), אבל
לפעמים עשויים להיות תיאורי שם או ביטויים
במקום זאת (לדוגמה, Readable
).
השמות של כיתות המבחנים מתחילים בשם הכיתה שבה הם בודקים.
ומסתיים בספרות Test
. לדוגמה, HashTest
או
HashIntegrationTest
.
שמות הפונקציות
שמות הפונקציות נכתבים בקאמל קייס, והם בדרך כלל פועלים או ביטויים של פועלים. לדוגמה, sendMessage
או stop
.
מותר להציג קווים תחתונים בשמות של פונקציות בדיקה כדי להפריד בין רכיבים לוגיים של השם.
@Test fun pop_emptyStack() { // … }
פונקציות המסומנות באמצעות @Composable
שמחזירות Unit
הן PascalCased ושמות להן שמות עצם, כאילו הן טיפוסים.
@Composable fun NameTag(name: String) { // … }
אסור לכלול רווחים בשמות הפונקציות כי האפשרות הזו לא נתמכת בכל בפלטפורמה (במיוחד אין תמיכה מלאה באפשרות הזו ב-Android).
// WRONG! fun `test every possible case`() {} // OK fun testEveryPossibleCase() {}
שמות קבועים
שמות קבועים משתמשים באותיות UPPER_SNAKE_CASE: כל האותיות צריכות להיות באותיות רישיות, כשהמילים מופרדות בקו תחתון. אבל מה זה קבוע, בדיוק?
קבועים הם מאפייני val
ללא פונקציית get
מותאמת אישית, שהתוכן שלהם הוא
שלא ניתנים לשינוי עמוק, ולפונקציות שלהן אין תופעות לוואי ניתנות לזיהוי. הזה
כולל סוגים שלא ניתנים לשינוי ואוספים שלא ניתנים לשינוי
וסקלרים ומחרוזות אם הם מסומנים כ-const
. אם מודל כלשהו
המצב הגלוי לכולם יכול להשתנות, הוא לא קבוע. מתוך כוונה
לא מספיק לבצע שינויים של האובייקט.
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()
שמות אלה הם בדרך כלל שמות עצם או ביטויים של שמות עצם.
אפשר להגדיר ערכים קבועים רק בתוך object
או כהצהרה ברמה עליונה. ערכים אחרים שעומדים בדרישה של
קבוע אבל מוגדר בתוך class
, חייב להשתמש בשם שאינו קבוע.
קבועים שהם ערכים סקלריים חייבים להשתמש בפונקציה const
modifier.
שמות לא קבועים
שמות לא קבועים נכתבים בקאמלזית. הכללים האלה רלוונטיים למאפייני מכונות, מאפיינים מקומיים ושמות פרמטרים.
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")
שמות אלה הם בדרך כלל שמות עצם או ביטויים של שמות עצם.
מתבצע גיבוי של המאפיינים
כאשר נכס גיבוי נדרש, השם שלו צריך להיות זהה לשם של הנכס האמיתי חוץ מאשר עם קו תחתון בתחילתו.
private var _table: Map? = null val table: Map get() { if (_table == null) { _table = HashMap() } return _table ?: throw AssertionError() }
צריך להקליד שמות של משתנים
לכל משתנה מסוג יש שם באחד משני סגנונות:
- אות גדולה אחת, וייתכן שאחריה יש
ספרה יחידה (כמו
E
,T
,X
,T2
) - שם בטופס שמשמש לסיווגים, ואחריו אותיות רישיות
האות
T
(למשלRequestT
,FooBarT
)
כיסוי לגמל
לפעמים יש יותר מדרך סבירה אחת להמיר ביטוי באנגלית לאותיות גמל, למשל כשמופיעים ראשי תיבות או מבנים מיוחדים כמו "IPv6" או "iOS". כדי לשפר את החיזוי, כדאי להשתמש בסכימה הבאה.
החל בצורת הפרוזה של השם:
- ממירים את הביטוי ל-ASCII פשוט ומסירים גרשיים. לדוגמה, 'האלגוריתם של מולר' עשוי להפוך ל'אלגוריתם Mullers'.
- ניתן לחלק את התוצאה הזו למילים, לפצל את הרווחים לפי רווחים ולפי סימני פיסוק שנותרו (בדרך כלל מקפים). מומלץ: אם למילה כלשהי כבר יש מראה קונבנציונלי של קאמל, יש לפצל אותה לחלקים השונים שלה (למשל, "AdWords" הופך ל"מילים של מודעות"). שימו לב שמילה כמו "iOS" אינה בהכרח שייכת לקמלים כשלעצמה; הוא נוגד מוסכמה כלשהי, ולכן ההמלצה הזו לא רלוונטית.
- עכשיו הכול באותיות קטנות (כולל ראשי תיבות), ולאחר מכן מבצעים אחת מהפעולות הבאות:
- כדי לקבל אותיות רישיות בתחילת כל מילה, יש להשתמש באותיות גדולות בתחילת כל מילה.
- אם יש אותיות גדולות בתחילת כל מילה, חוץ מהתו הראשון שיוצג קאמל קייס.
- לסיום, מאחדים את כל המילים למזהה אחד.
לתשומת ליבכם: המערכת מתעלמת כמעט לחלוטין מאותיות רישיות של המילים המקוריות.
צורת Prose | תקין | שגוי |
---|---|---|
"בקשת XML Http" | XmlHttpRequest |
XMLHTTPRequest |
מספר לקוח חדש | newCustomerId |
newCustomerID |
"שעון עצר פנימי" | innerStopwatch |
innerStopWatch |
"יש תמיכה ב-IPv6 ב-iOS" | supportsIpv6OnIos |
supportsIPv6OnIOS |
'יבואן YouTube' | YouTubeImporter |
YoutubeImporter * |
(* מקובל, אך לא מומלץ.)
מסמכים
עיצוב
ניתן לראות את העיצוב הבסיסי של בלוקים של KDoc בדוגמה הבאה:
/** * Multiple lines of KDoc text are written here, * wrapped normally… */ fun method(arg: String) { // … }
...או בדוגמה הזו של השורה היחידה:
/** An especially short bit of KDoc. */
הטופס הבסיסי תמיד קביל. טופס השורה היחידה יכול להיות
מוחלפים כאשר כל הבלוק של KDoc (כולל סמני תגובות)
יכולה להתאים לשורה אחת. לתשומת ליבכם: הכלל הזה חל רק כאשר אין
חסימת תגים כמו @return
.
פסקאות
שורה ריקה אחת – כלומר קו שמכיל רק את הכוכבית הראשית בקו
(*
) – מופיע בין פסקאות ולפני קבוצת תגי החסימה, אם יש כזו.
חסימת תגים
כל אחד מ'תגי החסימה' הרגילים שנעשה בהם שימוש מופיע לפי הסדר
@constructor
, @receiver
, @param
, @property
, @return
,
@throws
, @see
והם אף פעם לא מופיעים עם תיאור ריק.
כשתג בלוק לא מתאים לשורה אחת,
קווי המשך מוכנסים במרחק של 4 רווחים מהמיקום של @
.
קטע סיכום
כל בלוק KDoc מתחיל בקטע סיכום קצר. המקטע הזה הוא החלק היחיד בטקסט שמופיע בהקשרים מסוימים, למשל אינדקסים של מחלקה ו-method.
הטקסט הזה הוא חלק מביטוי, שהוא ביטוי של שם עצם או של פועל, ולא משפט שלם.
הוא לא מתחיל ב-"A `Foo` is a...
",
או "This method returns...
",
היא גם לא חייבת ליצור משפט חובה שלם כמו
'Save the record.
'. עם זאת, הקטע מופיע באותיות רישיות
סימני פיסוק כאילו היה משפט שלם.
שימוש
לכל הפחות, KDoc קיים לכל סוג של public
,
ולכל חבר public
או protected
מסוג כזה,
למעט כמה יוצאים מן הכלל שמפורטים בהמשך.
חריג: פונקציות עם הסבר עצמי
KDoc הוא אופציונלי לפונקציות "פשוטות וברורות" כמו getFoo
ומאפיינים כמו foo
, במקרים שבהם באמת ובאמת אין שום דבר כדאי יותר לומר מלבד "מחזיר ה-foo".
לא מתאים לצטט את החריגה הזו כדי להצדיק השמטת הרלוונטיות
מידע שקורא טיפוסי עשוי לדעת. לדוגמה,
פונקציה בשם getCanonicalName
או נכס בשם canonicalName
,
לא להשמיט את התיעוד שלו (עם הנימוקים שהוא אומר רק
/** Returns the canonical name. */
) אם לקורא טיפוסי אין
להבין מה המונח "שם קנוני" כלומר!
חריג: שינויים מברירת המחדל
KDoc לא תמיד נמצא בשיטה שמבטלת שיטת Supertype.