Kotlin語言學習筆記(2)

類(classes)

// 類聲明
class Invoice {
}
// 空的類
class Empty
// 主體構造器(primary constructor)
class Person constructor(firstName: String) {
}
// 省略了關鍵字的主體構造器
class Person(firstName: String) {
}
// 主體構造器的代碼必須寫在init(初始化)代碼塊裏面
class Customer(name: String) {
    init {
        logger.info("Customer initialized with value ${name}")
    }
}
// 屬性
class Customer(name: String) {
    val customerKey = name.toUpperCase()
}
// 主體構造器裏包含多個屬性
class Person(val firstName: String, val lastName: String, var age: Int) {
    // ...
}
// 帶註解和訪問權限的主體構造器 
class Customer public @Inject constructor(name: String) { ... }
// 從屬構造器(secondary constructor)
class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    }
}
// 從屬構造器調用主體構造器
class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
// 沒法建立實例的類,由於主體構造器被聲明爲私有訪問權限
class DontCreateMe private constructor () {
}
// 具備缺省值參數的主體構造器
class Customer(val customerName: String = "")
// 生成類的實例不須要new
val invoice = Invoice()
val customer = Customer("Joe Smith")

繼承(inheritance)

注意類和類中的方法在Kotlin語言中缺省不可繼承,須要被繼承的類和方法必須使用open關鍵字。
而接口和接口中的方法缺省可繼承,不須要open關鍵字。maven

// 隱式繼承自Any
class Example
// open表示可繼承
// 子類主體構造器調用基類主體構造器
open class Base(p: Int)
class Derived(p: Int) : Base(p)
// 子類從屬構造器調用基類的構造器
class MyView : View {
    constructor(ctx: Context) : super(ctx)
    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}
// 覆蓋基類的方法
open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
    override fun v() {}
}
// 覆蓋基類的方法但子類不可繼承
open class AnotherDerived() : Base() {
    final override fun v() {}
}
// 覆蓋基類的屬性
open class Foo {
    open val x: Int get { ... }
}
class Bar1 : Foo() {
    override val x: Int = ...
}
// 在主體構造器中覆蓋接口中的屬性
interface Foo {
    val count: Int
}
class Bar1(override val count: Int) : Foo
class Bar2 : Foo {
    override var count: Int = 0
}
// 使用特殊語法解決接口的多重繼承問題
// 接口中的方法都是open,便可繼承的
open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}
interface B {
    fun f() { print("B") }
    fun b() { print("b") }
}
class C() : A(), B {
    override fun f() {
        super<A>.f() // 調用 A.f()
        super<B>.f() // 調用 B.f()
    }
}
// 繼承基類的方法但不提供實現,子類仍然能夠是抽象類
open class Base {
    open fun f() {}
}
abstract class Derived : Base() {
    override abstract fun f()
}

屬性(properties)

// 屬性聲明
class Address {
    var name: String = ...
    var street: String = ...
    var city: String = ...
    var state: String? = ...
    var zip: String = ...
}
// 屬性訪問
fun copyAddress(address: Address): Address {
    val result = Address()
    result.name = address.name
    result.street = address.street
    // ...
    return result
}
// 可讀可寫屬性
var allByDefault: Int?
var initialized = 1
// 只讀屬性
val simple: Int?
val inferredType = 1
// 只讀屬性 自定義getter
val isEmpty: Boolean
    get() = this.size == 0
// 可讀可寫屬性 自定義getter setter
var stringRepresentation: String
    get() = this.toString()
    set(value) {
        setDataFromString(value)
    }
// 屬性類型自動推導
val isEmpty get() = this.size == 0
// setter爲公有但getter爲私有
var setterVisibility: String = "abc"
    private set
// setter帶註解
var setterWithAnnotation: Any? = null
    @Inject set
// 經過field標識符訪問屬性背後的字段(backing fields)
var counter = 0
    set(value) {
        if (value >= 0) field = value
    }
// 公有屬性以及背後的私有屬性(backing properties)
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        if (_table == null) {
            _table = HashMap()
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }
// 編譯期常量
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
// 須要延遲初始化的屬性使用 lateinit 來修飾
public class MyTest {
    lateinit var subject: TestSubject
    @SetUp fun setup() {
        subject = TestSubject()
    }
    @Test fun test() {
        subject.method()
    }
}

接口(interfaces)

// 接口中的方法能夠有缺省實現
interface MyInterface {
    fun bar()
    fun foo() {
      // ...
    }
}
// 在類中實現接口的方法
class Child : MyInterface {
    override fun bar() {
        // ...
    }
}
// 在類中實現接口的屬性
interface MyInterface {
    val prop: Int
    val propertyWithImplementation: String
        get() = "foo"
    fun foo() {
        print(prop)
    }
}
class Child : MyInterface {
    override val prop: Int = 29
}
// 使用特殊語法解決接口的多重繼承問題
interface A {
    fun foo() { print("A") }
    fun bar()
}
interface B {
    fun foo() { print("B") }
    fun bar() { print("bar") }
}
class C : A {
    override fun bar() { print("bar") }
}
class D : A, B {
    override fun foo() {
        super<A>.foo()
        super<B>.foo()
    }
    override fun bar() {
        super<B>.bar()
    }
}

可見性修飾符(visibility modifiers)

這個術語太怪癖,其實就是其餘語言中的訪問權限。
一共四種可見性(訪問權限):ide

  • private: 類或文件內可見
  • protected: private的可見性加上子類可見
  • internal: 模塊內可見
  • public: 處處可見

局部的變量,類以及函數沒有可見性。
模塊是指物理上的模塊(IntelliJ IDEA模塊,maven和gradle工程等)函數

// 文件示例
// file name: example.kt
package foo
private fun foo() {} // visible inside example.kt
public var bar: Int = 5 // property is visible everywhere
    private set         // setter is visible only in example.kt
internal val baz = 6    // visible inside the same module
// 類的示例
open class Outer {
    private val a = 1
    protected open val b = 2
    internal val c = 3
    val d = 4  // public by default
    protected class Nested {
        public val e: Int = 5
    }
}
class Subclass : Outer() {
    // a is not visible
    // b, c and d are visible
    // Nested and e are visible
    override val b = 5   // 'b' is protected
}
class Unrelated(o: Outer) {
    // o.a, o.b are not visible
    // o.c and o.d are visible (same module)
    // Outer.Nested is not visible, and Nested::e is not visible either 
}
// 主體構造器的可見性
class C private constructor(a: Int) { ... }

擴展(extensions)

包括擴展函數,擴展屬性
擴展函數能夠是全局的,也能夠聲明在某個類或伴生對象之中gradle

// 擴展函數(extension functions),內部使用 this 指代調用方對象
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2]
    this[index2] = tmp
}
val l = mutableListOf(1, 2, 3)
l.swap(0, 2)
// 靜態分發(dispatched statically)
open class C
class D: C()
fun C.foo() = "c"
fun D.foo() = "d"
fun printFoo(c: C) {
    println(c.foo())
}
printFoo(D()) // 輸出 c
// 同名時成員函數優先
class C {
    fun foo() { println("member") }
}
fun C.foo() { println("extension") }
c.foo() // member
// 能夠重載成員函數
class C {
    fun foo() { println("member") }
}
fun C.foo(i: Int) { println("extension") }
C().foo(1) // extension
// 擴展可空類型
fun Any?.toString(): String {
    if (this == null) return "null"
    return toString()
}
// 擴展屬性(extension properties)
val <T> List<T>.lastIndex: Int
    get() = size - 1
// 擴展伴生對象(companion object)
class MyClass {
    companion object { }  // will be called "Companion"
}
fun MyClass.Companion.foo() {
    // ...
}
// 擴展與包的關係
package foo.bar
fun Baz.goo() { ... } 
//
package com.example.usage
import foo.bar.goo
import foo.bar.*
fun usage(baz: Baz) {
    baz.goo()
}
// 分發接收者(dispatch receiver)及擴展接收者(extension receiver)
class D {
    fun bar() { ... }
}
class C {
    fun baz() { ... }
    fun D.foo() {
        bar()   // calls D.bar
        baz()   // calls C.baz
    }
    fun caller(d: D) {
        d.foo()   // call the extension function
    }
}
// 擴展接收者優先於分發接收者
class C {
    fun D.foo() {
        toString()         // calls D.toString()
        this@C.toString()  // calls C.toString()
    }
}
// 分發接收者有多態,擴展接收者沒有多態
open class D {
}
class D1 : D() {
}
open class C {
    open fun D.foo() {
        println("D.foo in C")
    }
    open fun D1.foo() {
        println("D1.foo in C")
    }
    fun caller(d: D) {
        d.foo()
    }
}
class C1 : C() {
    override fun D.foo() {
        println("D.foo in C1")
    }
    override fun D1.foo() {
        println("D1.foo in C1")
    }
}
C().caller(D())   // prints "D.foo in C"
C1().caller(D())  // prints "D.foo in C1" - dispatch receiver is resolved virtually
C().caller(D1())  // prints "D.foo in C" - extension receiver is resolved statically
相關文章
相關標籤/搜索