99re热视频这里只精品,久久久天堂国产精品女人,国产av一区二区三区,久久久精品成人免费看片,99久久精品免费看国产一区二区三区

Kotlin 類(lèi)和對(duì)象

2022-02-18 11:30 更新

類(lèi)定義

Kotlin 類(lèi)可以包含:構(gòu)造函數(shù)和初始化代碼塊、函數(shù)、屬性、內(nèi)部類(lèi)、對(duì)象聲明。

Kotlin 中使用關(guān)鍵字 class 聲明類(lèi),后面緊跟類(lèi)名:

class W3cschool{  // 類(lèi)名為 W3cschool
    // 大括號(hào)內(nèi)是類(lèi)體構(gòu)成
}

我們也可以定義一個(gè)空類(lèi):

class Empty

可以在類(lèi)中定義成員函數(shù):

class W3cschool() {
fun foo() { print("Foo") } // 成員函數(shù) }

類(lèi)的屬性

屬性定義

類(lèi)的屬性可以用關(guān)鍵字 var 聲明為可變的,否則使用只讀關(guān)鍵字 val 聲明為不可變。

class W3cschool{
var name: String = …… var url: String = …… var city: String = …… }

我們可以像使用普通函數(shù)那樣使用構(gòu)造函數(shù)創(chuàng)建類(lèi)實(shí)例:

val site = W3cschool() // Kotlin 中沒(méi)有 new 關(guān)鍵字

要使用一個(gè)屬性,只要用名稱(chēng)引用它即可

site.name           // 使用 . 號(hào)來(lái)引用
site.url

Koltin 中的類(lèi)可以有一個(gè) 主構(gòu)造器,以及一個(gè)或多個(gè)次構(gòu)造器,主構(gòu)造器是類(lèi)頭部的一部分,位于類(lèi)名稱(chēng)之后:

class Person constructor(firstName: String) {}

如果主構(gòu)造器沒(méi)有任何注解,也沒(méi)有任何可見(jiàn)度修飾符,那么constructor關(guān)鍵字可以省略。

class Person(firstName: String) {
}

getter 和 setter

屬性聲明的完整語(yǔ)法:

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]
 

getter 和 setter 都是可選

如果屬性類(lèi)型可以從初始化語(yǔ)句或者類(lèi)的成員函數(shù)中推斷出來(lái),那就可以省去類(lèi)型,val不允許設(shè)置setter函數(shù),因?yàn)樗侵蛔x的。

var allByDefault: Int? // 錯(cuò)誤: 需要一個(gè)初始化語(yǔ)句, 默認(rèn)實(shí)現(xiàn)了 getter 和 setter 方法
var initialized = 1    // 類(lèi)型為 Int, 默認(rèn)實(shí)現(xiàn)了 getter 和 setter
val simple: Int?       // 類(lèi)型為 Int ,默認(rèn)實(shí)現(xiàn) getter ,但必須在構(gòu)造函數(shù)中初始化
val inferredType = 1   // 類(lèi)型為 Int 類(lèi)型,默認(rèn)實(shí)現(xiàn) getter

實(shí)例

以下實(shí)例定義了一個(gè) Person 類(lèi),包含兩個(gè)可變變量 lastName 和 no,lastName 修改了 getter 方法,no 修改了 setter 方法。

class Person {

    var lastName: String = "zhang"
        get() = field.toUpperCase()   // 將變量賦值后轉(zhuǎn)換為大寫(xiě)
        set

    var no: Int = 100
        get() = field                // 后端變量
        set(value) {
            if (value < 10) {       // 如果傳入的值小于 10 返回該值
                field = value
            } else {
                field = -1         // 如果傳入的值大于等于 10 返回 -1
            }
        }

    var heiht: Float = 145.4f
        private set
}

// 測(cè)試
fun main(args: Array<String>) {
    var person: Person = Person()

    person.lastName = "wang"

    println("lastName:${person.lastName}")

    person.no = 9
    println("no:${person.no}")

    person.no = 20
    println("no:${person.no}")

}

輸出結(jié)果為:

lastName:WANG
no:9
no:-1

Kotlin 中類(lèi)不能有字段。提供了 Backing Fields(后端變量) 機(jī)制,備用字段使用field關(guān)鍵字聲明,field 關(guān)鍵詞只能用于屬性的訪問(wèn)器,如以上實(shí)例:

var no: Int = 100
        get() = field                // 后端變量
        set(value) {
            if (value < 10) {       // 如果傳入的值小于 10 返回該值
                field = value
            } else {
                field = -1         // 如果傳入的值大于等于 10 返回 -1
            }
        }

非空屬性必須在定義的時(shí)候初始化,kotlin提供了一種可以延遲初始化的方案,使用 lateinit 關(guān)鍵字描述屬性:

public class MyTest {
    lateinit var subject: TestSubject

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {
        subject.method()  // dereference directly
    }
}

主構(gòu)造器

主構(gòu)造器中不能包含任何代碼,初始化代碼可以放在初始化代碼段中,初始化代碼段使用 init 關(guān)鍵字作為前綴。

class Person constructor(firstName: String) {
    init {
        println("FirstName is $firstName")
    }
}

注意:主構(gòu)造器的參數(shù)可以在初始化代碼段中使用,也可以在類(lèi)主體n定義的屬性初始化代碼中使用。 一種簡(jiǎn)潔語(yǔ)法,可以通過(guò)主構(gòu)造器來(lái)定義屬性并初始化屬性值(可以是var或val):

class People(val firstName: String, val lastName: String) {
    //...
}

如果構(gòu)造器有注解,或者有可見(jiàn)度修飾符,這時(shí)constructor關(guān)鍵字是必須的,注解和修飾符要放在它之前。

實(shí)例

創(chuàng)建一個(gè) W3cschool類(lèi),并通過(guò)構(gòu)造函數(shù)傳入網(wǎng)站名:

class W3cschool constructor(name: String) {  // 類(lèi)名為 W3cschool
// 大括號(hào)內(nèi)是類(lèi)體構(gòu)成 var url: String = "http://www.w3cschool.com"
var country: String = "CN" var siteName = name init { println("初始化網(wǎng)站名: ${name}") } fun printTest() { println("我是類(lèi)的函數(shù)") } } fun main(args: Array<String>) { val w3cschool= W3cschool("編程獅")
println(w3cschool.siteName)
println(w3cschool.url)
println(w3cschool.country)
w3cschool.printTest()
}

輸出結(jié)果為:

初始化網(wǎng)站名: 編程獅
編程獅
http://www.w3cschool.com
CN 我是類(lèi)的函數(shù)

次構(gòu)造函數(shù)

類(lèi)也可以有二級(jí)構(gòu)造函數(shù),需要加前綴 constructor:

class Person { 
    constructor(parent: Person) {
        parent.children.add(this) 
    }
}

如果類(lèi)有主構(gòu)造函數(shù),每個(gè)次構(gòu)造函數(shù)都要,或直接或間接通過(guò)另一個(gè)次構(gòu)造函數(shù)代理主構(gòu)造函數(shù)。在同一個(gè)類(lèi)中代理另一個(gè)構(gòu)造函數(shù)使用 this 關(guān)鍵字:

class Person(val name: String) {
    constructor (name: String, age:Int) : this(name) {
        // 初始化...
    }
}

如果一個(gè)非抽象類(lèi)沒(méi)有聲明構(gòu)造函數(shù)(主構(gòu)造函數(shù)或次構(gòu)造函數(shù)),它會(huì)產(chǎn)生一個(gè)沒(méi)有參數(shù)的構(gòu)造函數(shù)。構(gòu)造函數(shù)是 public 。如果你不想你的類(lèi)有公共的構(gòu)造函數(shù),你就得聲明一個(gè)空的主構(gòu)造函數(shù):

class DontCreateMe private constructor () {
}
注意:在 JVM 虛擬機(jī)中,如果主構(gòu)造函數(shù)的所有參數(shù)都有默認(rèn)值,編譯器會(huì)生成一個(gè)附加的無(wú)參的構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)會(huì)直接使用默認(rèn)值。這使得 Kotlin 可以更簡(jiǎn)單的使用像 Jackson 或者 JPA 這樣使用無(wú)參構(gòu)造函數(shù)來(lái)創(chuàng)建類(lèi)實(shí)例的庫(kù)。class Customer(val customerName: String = "")

實(shí)例

class W3cschool constructor(name: String) {  // 類(lèi)名為 W3cschool 
// 大括號(hào)內(nèi)是類(lèi)體構(gòu)成 var url: String = "http://www.w3cschool .com"
var country: String = "CN" var siteName = name init { println("初始化網(wǎng)站名: ${name}") } // 次構(gòu)造函數(shù) constructor (name: String, alexa: Int) : this(name) { println("Alexa 排名 $alexa") } fun printTest() { println("我是類(lèi)的函數(shù)") } } fun main(args: Array<String>) { val w3cschool = W3cschool ("編程獅", 10000)
println(w3cschool .siteName)
println(w3cschool .url)
println(w3cschool .country)
w3cschool .printTest()
}

輸出結(jié)果為:

初始化網(wǎng)站名: 編程獅
Alexa 排名 10000
編程獅
http://www.w3cschool.com
CN 我是類(lèi)的函數(shù)

抽象類(lèi)

抽象是面向?qū)ο缶幊痰奶卣髦?,?lèi)本身,或類(lèi)中的部分成員,都可以聲明為abstract的。抽象成員在類(lèi)中不存在具體的實(shí)現(xiàn)。

注意:無(wú)需對(duì)抽象類(lèi)或抽象成員標(biāo)注open注解。

open class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()
}

嵌套類(lèi)

我們可以把類(lèi)嵌套在其他類(lèi)中,看以下實(shí)例:

class Outer {                  // 外部類(lèi)
    private val bar: Int = 1
    class Nested {             // 嵌套類(lèi)
        fun foo() = 2
    }
}

fun main(args: Array<String>) {
    val demo = Outer.Nested().foo() // 調(diào)用格式:外部類(lèi).嵌套類(lèi).嵌套類(lèi)方法/屬性
    println(demo)    // == 2
}

內(nèi)部類(lèi)

內(nèi)部類(lèi)使用 inner 關(guān)鍵字來(lái)表示。

內(nèi)部類(lèi)會(huì)帶有一個(gè)對(duì)外部類(lèi)的對(duì)象的引用,所以?xún)?nèi)部類(lèi)可以訪問(wèn)外部類(lèi)成員屬性和成員函數(shù)。

class Outer {
    private val bar: Int = 1
    var v = "成員屬性"
    /**嵌套內(nèi)部類(lèi)**/
    inner class Inner {
        fun foo() = bar  // 訪問(wèn)外部類(lèi)成員
        fun innerTest() {
            var o = this@Outer //獲取外部類(lèi)的成員變量
            println("內(nèi)部類(lèi)可以引用外部類(lèi)的成員,例如:" + o.v)
        }
    }
}

fun main(args: Array<String>) {
    val demo = Outer().Inner().foo()
    println(demo) //   1
    val demo2 = Outer().Inner().innerTest()   
    println(demo2)   // 內(nèi)部類(lèi)可以引用外部類(lèi)的成員,例如:成員屬性
}

為了消除歧義,要訪問(wèn)來(lái)自外部作用域的 this,我們使用this@label,其中 @label 是一個(gè) 代指 this 來(lái)源的標(biāo)簽。

匿名內(nèi)部類(lèi)

使用對(duì)象表達(dá)式來(lái)創(chuàng)建匿名內(nèi)部類(lèi):

class Test {
    var v = "成員屬性"

    fun setInterFace(test: TestInterFace) {
        test.test()
    }
}

/**
 * 定義接口
 */
interface TestInterFace {
    fun test()
}

fun main(args: Array<String>) {
    var test = Test()

    /**
     * 采用對(duì)象表達(dá)式來(lái)創(chuàng)建接口對(duì)象,即匿名內(nèi)部類(lèi)的實(shí)例。
     */
    test.setInterFace(object : TestInterFace {
        override fun test() {
            println("對(duì)象表達(dá)式創(chuàng)建匿名內(nèi)部類(lèi)的實(shí)例")
        }
    })
}

類(lèi)的修飾符

類(lèi)的修飾符包括 classModifier 和_accessModifier_:

  • classModifier: 類(lèi)屬性修飾符,標(biāo)示類(lèi)本身特性。abstract // 抽象類(lèi) final // 類(lèi)不可繼承,默認(rèn)屬性 enum // 枚舉類(lèi) open // 類(lèi)可繼承,類(lèi)默認(rèn)是final的 annotation // 注解類(lèi)
  • accessModifier: 訪問(wèn)權(quán)限修飾符private // 僅在同一個(gè)文件中可見(jiàn) protected // 同一個(gè)文件中或子類(lèi)可見(jiàn) public // 所有調(diào)用的地方都可見(jiàn) internal // 同一個(gè)模塊中可見(jiàn)

實(shí)例

// 文件名:example.kt
package foo

private fun foo() {} // 在 example.kt 內(nèi)可見(jiàn)

public var bar: Int = 5 // 該屬性隨處可見(jiàn)

internal val baz = 6    // 相同模塊內(nèi)可見(jiàn)


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)