<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 編碼規范 本頁包含當前 Kotlin 語言的編碼風格。 [TOC] ### 應用風格指南 如需根據本風格指南配置 IntelliJ 格式化程序,請安裝 Kotlin 插件1.2.20 或更高版本,轉到 __Settings | Editor | Code Style | Kotlin__,點擊右上角的 __Set from...__ 鏈接,并從菜單中選擇 __Predefined style | Kotlin style guide__。 如需驗證代碼已按風格指南格式化,請轉到探查設置(Inspections)并啟用__Kotlin | Style issues | File is not formatted according to project settings__ 探查項。 驗證風格指南中描述的其他問題(如命名約定)的附加探查項默認已啟用。 ## 源代碼組織 ### 目錄結構 在純 Kotlin 項目中,推薦的目錄結構遵循省略了公共根包的包結構。例如,如果項目中的所有代碼都位于`org.example.kotlin` 包及其子包中,那么 `org.example.kotlin` 包的文件應該直接放在源代碼根目錄下,而`org.example.kotlin.network.socket` 中的文件應該放在源代碼根目錄下的 `network/socket` 子目錄中。 > **對于 JVM 平臺**:Kotlin 源文件應當與 Java 源文件位于同一源文件根目錄下,并遵循相同的目錄結構(每個文件應存儲在與其 package 語句對應的目錄中。 ### 源文件名稱 如果 Kotlin 文件包含單個類(以及可能相關的頂層聲明),那么文件名應該與該類的名稱相同,并追加 .kt 擴展名。如果文件包含多個類或只包含頂層聲明,那么選擇一個描述該文件所包含內容的名稱,并以此命名該文件。使用首字母大寫的駝峰風格(例如 `ProcessDeclarations.kt`)。 文件的名稱應該描述文件中代碼的作用。因此,應避免在文件名中使用諸如“Util”之類的無意義詞語。 ### 源文件組織 鼓勵多個聲明(類、頂級函數或者屬性)放在同一個 Kotlin 源文件中,只要這些聲明在語義上彼此緊密關聯并且文件保持合理大小(不超過幾百行)。 特別是在為類定義與類的所有客戶都相關的擴展函數時,請將它們放在與類自身定義相同的地方。而在定義僅對指定客戶有意義的擴展函數時,請將它們放在緊挨該客戶代碼之后。不要只是為了保存“Foo 的所有擴展函數”而創建文件。 ### 類布局 通常,一個類的內容按以下順序排列: - 屬性聲明與初始化塊 - 次構造函數 - 方法聲明 - 伴生對象 不要按字母順序或者可見性對方法聲明排序,也不要將常規方法與擴展方法分開。而是要把相關的東西放在一起,這樣從上到下閱讀類的人就能夠跟進所發生事情的邏輯。選擇一個順序(高級別優先,或者相反)并堅持下去。 將嵌套類放在緊挨使用這些類的代碼之后。如果打算在外部使用嵌套類,而且類中并沒有引用這些類,那么把它們放到末尾,在伴生對象之后。 ### 接口實現布局 在實現一個接口時,實現成員的順序應該與該接口的成員順序相同(如果需要,還要插入用于實現的額外的私有方法) ### 重載布局 在類中總是將重載放在一起。 ## 命名規則 在 Kotlin 中,包名與類名的命名規則非常簡單: * 包的名稱總是小寫且不使用下劃線(`org.example.project`)。 通常不鼓勵使用多個詞的名稱,但是如果確實需要使用多個詞,可以將它們連接在一起或使用駝峰(`org.example.myProject`)。 * 類與對象的名稱以大寫字母開頭并使用駝峰: ```kotlin open class DeclarationProcessor { …… } object EmptyDeclarationProcessor : DeclarationProcessor() { …… } ``` ### 函數名 函數、屬性與局部變量的名稱以小寫字母開頭、使用駝峰而不使用下劃線: ```kotlin fun processDeclarations() { …… } var declarationCount = …… ``` 例外:用于創建類實例的工廠函數可以與要創建的類具有相同的名稱: ```kotlin abstract class Foo { …… } class FooImpl : Foo { …… } fun Foo(): Foo { return FooImpl(……) } ``` #### 測試方法的名稱 當且僅當在測試中,可以使用反引號括起來的帶空格的方法名。(請注意,Android 運行時目前不支持這樣的方法名。)測試代碼中也允許方法名使用下劃線。 ```kotlin class MyTestCase { @Test fun `ensure everything works`() { ... } @Test fun ensureEverythingWorks_onAndroid() { ... } } ``` ### 屬性名 常量名稱(標有 `const` 的屬性,或者保存不可變數據的沒有自定義 `get` 函數的頂層/對象 `val` 屬性)應該使用大寫、下劃線分隔的名稱: ```kotlin const val MAX_COUNT = 8 val USER_NAME_FIELD = "UserName" ``` 保存帶有行為的對象或者可變數據的頂層/對象屬性的名稱應該使用常規駝峰名稱: ```kotlin val mutableCollection: MutableSet<String> = HashSet() ``` 保存單例對象引用的屬性的名稱可以使用與 `object` 聲明相同的命名風格: ```kotlin val PersonComparator: Comparator<Person> = ... ``` 對于枚舉常量,可以使用大寫、下劃線分隔的名稱 (`enum class Color { RED, GREEN }`)也可使用以大寫字母開頭的常規駝峰名稱,具體取決于用途。 #### 幕后屬性的名稱 如果一個類有兩個概念上相同的屬性,一個是公共 API 的一部分,另一個是實現細節,那么使用下劃線作為私有屬性名稱的前綴: ```kotlin class C { private val _elementList = mutableListOf<Element>() val elementList: List<Element> get() = _elementList } ``` ### 選擇好名稱 類的名稱通常是用來解釋類*是*什么的名詞或者名詞短語:`List`、 `PersonReader`。 方法的名稱通常是動詞或動詞短語,說明該方法*做*什么:`close`、 `readPersons`。 修改對象或者返回一個新對象的名稱也應遵循建議。例如 `sort` 是對一個集合就地排序,而 `sorted` 是返回一個排序后的集合副本。 名稱應該表明實體的目的是什么,所以最好避免在名稱中使用無意義的單詞(`Manager`、 `Wrapper` 等)。 當使用首字母縮寫作為名稱的一部分時,如果縮寫由兩個字母組成,就將其大寫(`IOStream`); 而如果縮寫更長一些,就只大寫其首字母(`XmlFormatter`、 `HttpInputStream`)。 ## 格式化 使用 4 個空格縮進。不要使用 tab。 對于花括號,將左花括號放在結構起始處的行尾,而將右花括號放在與左括結構橫向對齊的單獨一行 ```kotlin if (elements != null) { for (element in elements) { // …… } } ``` >[info]注意:在 Kotlin 中,分號是可選的,因此換行很重要。語言設計采用Java 風格的花括號格式,如果嘗試使用不同的格式化風格,那么可能會遇到意外的行為。 ### 橫向空白 在二元操作符左右留空格(`a + b`)。例外:不要在“range to”操作符(`0..i`)左右留空格。 不要在一元運算符左右留空格(`a++`) 在控制流關鍵字(`if`、 `when`、 `for` 以及 `while`)與相應的左括號之間留空格。 不要在主構造函數聲明、方法聲明或者方法調用的左括號之前留空格。 ```kotlin class A(val x: Int) fun foo(x: Int) { …… } fun bar() { foo(1) } ``` 絕不在 `(`、 `[` 之后或者 `]`、 `)` 之前留空格。 絕不在`.` 或者 `?.` 左右留空格:`foo.bar().filter { it > 2 }.joinToString()`, `foo?.bar()` 在 `//` 之后留一個空格:`// 這是一條注釋` 不要在用于指定類型參數的尖括號前后留空格:`class Map<K, V> { …… }` 不要在 `::` 前后留空格:`Foo::class`、 `String::length` 不要在用于標記可空類型的 `?` 前留空格:`String?` 作為一般規則,避免任何類型的水平對齊。將標識符重命名為不同長度的名稱不應該影響聲明或者任何用法的格式。 ### 冒號 在以下場景中的 `:` 之前留一個空格: * 當它用于分隔類型與超類型時; * 當委托給一個超類的構造函數或者同一類的另一個構造函數時; * 在 `object` 關鍵字之后。 而當分隔聲明與其類型時,不要在 `:` 之前留空格。在 `:` 之后總要留一個空格。 ```kotlin abstract class Foo<out T : Any> : IFoo { abstract fun foo(a: Int): T } class FooImpl : Foo() { constructor(x: String) : this(x) { …… } val x = object : IFoo { …… } } ``` ### 類頭格式化 具有少數主構造函數參數的類可以寫成一行: ```kotlin class Person(id: Int, name: String) ``` 具有較長類頭的類應該格式化,以使每個主構造函數參數都在帶有縮進的獨立的行中。另外,右括號應該位于一個新行上。如果使用了繼承,那么超類的構造函數調用或者所實現接口的列表應該與右括號位于同一行: ```kotlin class Person( id: Int, name: String, surname: String ) : Human(id, name) { …… } ``` 對于多個接口,應該將超類構造函數調用放在首位,然后將每個接口應放在不同的行中: ```kotlin class Person( id: Int, name: String, surname: String ) : Human(id, name), KotlinMaker { …… } ``` 對于具有很長超類型列表的類,在冒號后面換行,并橫向對齊所有超類型名: ```kotlin class MyFavouriteVeryLongClassHolder : MyLongHolder<MyFavouriteVeryLongClass>(), SomeOtherInterface, AndAnotherOne { fun foo() { ... } } ``` 為了將類頭與類體分隔清楚,當類頭很長時,可以在類頭后放一空行(如上例所示)或者將左花括號放在獨立行上: ```kotlin class MyFavouriteVeryLongClassHolder : MyLongHolder<MyFavouriteVeryLongClass>(), SomeOtherInterface, AndAnotherOne { fun foo() { ... } } ``` 構造函數參數使用常規縮進(4 個空格)。 > 理由:這確保了在主構造函數中聲明的屬性與 在類體中聲明的屬性具有相同的縮進。 ### 修飾符 如果一個聲明有多個修飾符,請始終按照以下順序安放: ```kotlin public / protected / private / internal expect / actual final / open / abstract / sealed / const external override lateinit tailrec vararg suspend inner enum / annotation companion inline infix operator data ``` 將所有注解放在修飾符前: ```kotlin @Named("Foo") private val foo: Foo ``` 除非你在編寫庫,否則請省略多余的修飾符(例如 `public`)。 ### 注解格式化 注解通常放在單獨的行上,在它們所依附的聲明之前,并使用相同的縮進: ``` @Target(AnnotationTarget.PROPERTY) annotation class JsonExclude ``` 無參數的注解可以放在同一行: ```kotlin @JsonExclude @JvmField var x: String ``` 無參數的單個注解可以與相應的聲明放在同一行: ```kotlin @Test fun foo() { …… } ``` ### 文件注解 文件注解位于文件注釋(如果有的話)之后、`package` 語句之前,并且用一個空白行與 `package` 分開(為了強調其針對文件而不是包)。 ```kotlin /** 授權許可、版權以及任何其他內容 */ @file:JvmName("FooBar") package foo.bar ``` ### 函數格式化 如果函數簽名不適合單行,請使用以下語法: ```kotlin fun longMethodName( argument: ArgumentType = defaultValue, argument2: AnotherArgumentType ): ReturnType { // 函數體 } ``` 函數參數使用常規縮進(4 個空格)。 > 理由:與構造函數參數一致 對于由單個表達式構成的函數體,優先使用表達式形式。 ```kotlin fun foo(): Int { // 不良 return 1 } fun foo() = 1 // 良好 ``` ### 表達式函數體格式化 如果函數的表達式函數體與函數聲明不適合放在同一行,那么將 `=` 留在第一行。將表達式函數體縮進 4 個空格。 ```kotlin fun f(x: String) = x.length ``` ### 屬性格式化 對于非常簡單的只讀屬性,請考慮單行格式: ```kotlin val isEmpty: Boolean get() = size == 0 ``` 對于更復雜的屬性,總是將 `get` 與 `set` 關鍵字放在不同的行上: ```kotlin val foo: String get() { …… } ``` 對于具有初始化器的屬性,如果初始化器很長,那么在等號后增加一個換行<并將初始化器縮進四個空格: ```kotlin private val defaultCharset: Charset? = EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file) ``` ### 格式化控制流語句 如果 `if` 或 `when` 語句的條件有多行,那么在語句體外邊總是使用大括號。 將該條件的每個后續行相對于條件語句起始處縮進 4 個空格。 將該條件的右圓括號與左花括號放在單獨一行: ```kotlin if (!component.isSyncing && !hasAnyKotlinRuntimeInScope(module) ) { return createKotlinNotConfiguredPanel(module) } ``` > 理由:對齊整齊并且將條件與語句體分隔清楚 將 `else`、 `catch`、 `finally` 關鍵字以及 do/while 循環的 `while` 關鍵字與之前的花括號放在相同的行上: ```kotlin if (condition) { // 主體 } else { // else 部分 } try { // 主體 } finally { // 清理 } ``` 在 `when` 語句中,如果一個分支不止一行,可以考慮用空行將其與相鄰的分支塊分開: ```kotlin private fun parsePropertyValue(propName: String, token: Token) { when (token) { is Token.ValueToken -> callback.visitValue(propName, token.value) Token.LBRACE -> { // …… } } } ``` 將短分支放在與條件相同的行上,無需花括號。 ```kotlin when (foo) { true -> bar() // 良好 false -> { baz() } // 不良 } ``` ### 方法調用格式化 在較長參數列表的左括號后添加一個換行符。按 4 個空格縮進參數。將密切相關的多個參數分在同一行。 ```kotlin drawSquare( x = 10, y = 10, width = 100, height = 100, fill = true ) ``` 在分隔參數名與值的 `=` 左右留空格。 ### 鏈式調用換行 當對鏈式調用換行時,將 `.` 字符或者 `?.` 操作符放在下一行,并帶有單倍縮進: ```kotlin val anchor = owner ?.firstChild!! .siblings(forward = true) .dropWhile { it is PsiComment || it is PsiWhiteSpace } ``` 調用鏈的第一個調用通常在換行之前,當然如果能讓代碼更有意義也可以忽略這點。 ### Lambda 表達式格式化 在 lambda 表達式中,應該在花括號左右以及分隔參數與代碼體的箭頭左右留空格。 如果一個調用接受單個 lambda 表達式,應該盡可能將其放在圓括號外邊傳入。 ```kotlin list.filter { it > 10 } ``` 如果為 lambda 表達式分配一個標簽,那么不要在該標簽與左花括號之間留空格: ```kotlin fun foo() { ints.forEach lit@{ // …… } } ``` 在多行的 lambda 表達式中聲明參數名時,將參數名放在第一行,后跟箭頭與換行符: ```kotlin appendCommaSeparated(properties) { prop -> val propertyValue = prop.get(obj) // …… } ``` 如果參數列表太長而無法放在一行上,請將箭頭放在單獨一行: ```kotlin foo { context: Context, environment: Env -> context.configureEnv(environment) } ``` ## 文檔注釋 對于較長的文檔注釋,將開頭 `/**` 放在一個獨立行中,并且后續每行都以星號開頭: ```kotlin /** * 這是一條多行 * 文檔注釋。 */ ``` 簡短注釋可以放在一行內: ```kotlin /** 這是一條簡短文檔注釋。 */ ``` 通常,避免使用 `@param` 與 `@return` 標記。而是將參數與返回值的描述直接合并到文檔注釋中,并在提到參數的任何地方加上參數鏈接。 只有當需要不適合放進主文本流程的冗長描述時才應使用 `@param` 與 `@return`。 ```kotlin // 避免這樣: /** * Returns the absolute value of the given number. * @param number The number to return the absolute value for. * @return The absolute value. */ fun abs(number: Int) = …… // 而要這樣: /** * Returns the absolute value of the given [number]. */ fun abs(number: Int) = …… ``` ## 避免重復結構 一般來說,如果 Kotlin 中的某種語法結構是可選的并且被 IDE高亮為冗余的,那么應該在代碼中省略之。為了清楚起見,不要在代碼中保留不必要的語法元素。 ### Unit 如果函數返回 Unit,那么應該省略返回類型: ```kotlin fun foo() { // 這里省略了“: Unit” } ``` ### 分號 盡可能省略分號。 ### 字符串模版 將簡單變量傳入到字符串模版中時不要使用花括號。只有用到更長表達式時才使用花括號。 ```kotlin println("$name has ${children.size} children") ``` ## 語言特性的慣用法 ### 不可變性 優先使用不可變(而不是可變)數據。初始化后未修改的局部變量與屬性,總是將其聲明為 `val` 而不是 `var`。 總是使用不可變集合接口(`Collection`, `List`, `Set`, `Map`)來聲明無需改變的集合。使用工廠函數創建集合實例時,盡可能選用返回不可變集合類型的函數: ```kotlin // 不良:使用可變集合類型作為無需改變的值 fun validateValue(actualValue: String, allowedValues: HashSet<String>) { …… } // 良好:使用不可變集合類型 fun validateValue(actualValue: String, allowedValues: Set<String>) { …… } // 不良:arrayListOf() 返回 ArrayList<T>,這是一個可變集合類型 val allowedValues = arrayListOf("a", "b", "c") // 良好:listOf() 返回 List<T> val allowedValues = listOf("a", "b", "c") ``` ### 默認參數值 優先聲明帶有默認參數的函數而不是聲明重載函數。 ```kotlin // 不良 fun foo() = foo("a") fun foo(a: String) { …… } // 良好 fun foo(a: String = "a") { …… } ``` ### 類型別名 如果有一個在代碼庫中多次用到的函數類型或者帶有類型參數的類型,那么最好為它定義一個類型別名: ```kotlin typealias MouseClickHandler = (Any, MouseEvent) -> Unit typealias PersonIndex = Map<String, Person> ``` ### Lambda 表達式參數 在簡短、非嵌套的 lambda 表達式中建議使用 `it` 用法而不是顯式聲明參數。而在有參數的嵌套 lambda 表達式中,始終應該顯式聲明參數。 ### 在 lambda 表達式中返回 避免在 lambda 表達式中使用多個返回到標簽。請考慮重新組織這樣的 lambda 表達式使其只有單一退出點。 如果這無法做到或者不夠清晰,請考慮將 lambda 表達式轉換為匿名函數。 不要在 lambda 表達式的最后一條語句中使用返回到標簽。 ### 命名參數 當一個方法接受多個相同的原生類型參數或者多個 `Boolean` 類型參數時,請使用命名參數語法,除非在上下文中的所有參數的含義都已絕對清楚。 ```kotlin drawSquare(x = 10, y = 10, width = 100, height = 100, fill = true) ``` ### 使用條件語句 優先使用 `try`、`if` 與 `when` 的表達形式。例如: ```kotlin return if (x) foo() else bar() return when(x) { 0 -> "zero" else -> "nonzero" } ``` 優先選用上述代碼而不是: ```kotlin if (x) return foo() else return bar() when(x) { 0 -> return "zero" else -> return "nonzero" } ``` ### `if` 還是 `when` 二元條件優先使用 `if` 而不是 `when`。不要使用 ```kotlin when (x) { null -> …… else -> …… } ``` 而應使用 `if (x == null) …… else ……` 如果有三個或多個選項時優先使用 `when`。 ### 在條件中使用可空的 `Boolean` 值 如果需要在條件語句中用到可空的 `Boolean`, 使用 `if (value == true)` 或 `if (value == false)` 檢測。 ### 使用循環 優先使用高階函數(`filter`、`map` 等)而不是循環。例外:`forEach`(優先使用常規的 `for` 循環, 除非 `forEach` 的接收者是可空的或者 `forEach` 用做長調用鏈的一部分。) 當在使用多個高階函數的復雜表達式與循環之間進行選擇時,請了解每種情況下所執行操作的開銷并且記得考慮性能因素。 ### 區間上循環 使用 `until` 函數在一個開區間上循環: ```kotlin for (i in 0..n - 1) { …… } // 不良 for (i in 0 until n) { …… } // 良好 ``` ### 使用字符串 優先使用字符串模板而不是字符串拼接。 優先使用多行字符串而不是將 `\n` 轉義序列嵌入到常規字符串字面值中。 如需在多行字符串中維護縮進,當生成的字符串不需要任何內部縮進時使用 `trimIndent`,而需要內部縮進時使用 `trimMargin`: ```kotlin assertEquals( """ Foo Bar """.trimIndent(), value ) val a = """if(a > 1) { | return a |}""".trimMargin() ``` ### 函數還是屬性 在某些情況下,不帶參數的函數可與只讀屬性互換。雖然語義相似,但是在某種程度上有一些風格上的約定。 底層算法優先使用屬性而不是函數: * 不會拋異常 * 計算開銷小(或者在首次運行時緩存) * 如果對象狀態沒有改變,那么多次調用都會返回相同結果 ### 使用擴展函數 放手去用擴展函數。每當你有一個主要用于某個對象的函數時,可以考慮使其成為一個以該對象為接收者的擴展函數。為了盡量減少 API 污染,盡可能地限制擴展函數的可見性。根據需要,使用局部擴展函數、成員擴展函數或者具有私有可視性的頂層擴展函數。 ### 使用中綴函數 一個函數只有用于兩個角色類似的對象時才將其聲明為中綴函數。良好示例如:`and`、 `to`、`zip`。不良示例如:`add`。如果一個方法會改動其接收者,那么不要聲明為中綴形式。 ### 工廠函數 如果為一個類聲明一個工廠函數,那么不要讓它與類自身同名。優先使用獨特的名稱,該名稱能表明為何該工廠函數的行為與眾不同。只有當確實沒有特殊的語義時,才可以使用與該類相同的名稱。 例如: ```kotlin class Point(val x: Double, val y: Double) { companion object { fun fromPolar(angle: Double, radius: Double) = Point(...) } } ``` 如果一個對象有多個重載的構造函數,它們并非調用不同的超類構造函數,并且不能簡化為具有默認參數值的單個構造函數,那么優先用工廠函數取代這些重載的構造函數。 ### 平臺類型 返回平臺類型表達式的公有函數/方法必須顯式聲明其 Kotlin 類型: ```kotlin fun apiCall(): String = MyJavaApi.getProperty("name") ``` 任何使用平臺類型表達式初始化的屬性(包級別或類級別)必須顯式聲明其 Kotlin 類型: ```kotlin class Person { val name: String = MyJavaApi.getProperty("name") } ``` 使用平臺類型表達式初始化的局部值可以有也可以沒有類型聲明: ```kotlin fun main() { val name = MyJavaApi.getProperty("name") println(name) } ``` ### 使用作用域函數 apply/with/run/also/let Kotlin 提供了一系列用來在給定對象上下文中執行代碼塊的函數:`let`、 `run`、 `with`、 `apply` 以及 `also`。 關于不同情況下選擇正確作用域函數的準則,請參考[作用域函數](scope-functions.html)。 ## 庫的編碼規范 在編寫庫時,建議遵循一組額外的規則以確保 API 的穩定性: * 總是顯式指定成員的可見性(以避免將聲明意外暴露為公有 API ) * 總是顯式指定函數返回類型以及屬性類型(以避免當實現改變時意外更改返回類型) * 為所有公有成員提供 KDoc 注釋,不需要任何新文檔的覆蓋成員除外(以支持為該庫生成文檔)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看