Kotlin Reference (五) 类的构造函数,类的继承,属性操作

KotLin 相关文档


官方在线Reference
kotlin-docs.pdf
Kotlin for android Developers 中文翻译
Kotlin开发工具集成,相关平台支持指南
Kotlin开源项目与Libraries
Kotlin开源项目、资源、书籍及课程搜索平台
Google’s sample projects written in Kotlin
Kotlin and Android

 

Constructors


下面的代码示例了:

使用constructor,声明构造函数;
init { } 初始化语句块;

//import kotlin.reflect.jvm.internal.impl.javax.inject.Inject

/**
 * desc  :
 * author: stone
 * email : [email protected]
 * time  : 31/05/2017 15 44
 */
class Person1 constructor(firstName: String) {}//主构造函数可以直接定义在类名后
class Person2 constructor(val firstName: String) { }
class Person3 constructor(var firstName: String) { }
class Person4(firstName: String) { } //如果主构造函数没有任何注解或可见性修饰符,构造函数关键字可以省略

class Person5(name: String) {//若主构造函数中,不进行初始化, 可放在init{}中
    val name: String
    init {
        println("initialize")
        this.name = name
    }
}

class Person6(name: String) {//主构造函数中的参数初始化,也可以用在成员属性上
    val name = String
//    val name: String = name
}

//如果主构造函数前有可见性修饰符或注解,就一定需要加上constructor 关键字
class Person7 private/* @Inject*/ constructor(name:String, age: Int)

/*
当有其它构造函数,依赖主构造函数,形如 constructor(...) : this(...)
对于 主构造函数中的参数,如上所说,要么放在init{} ,要么以赋值给成员属性
对于 非主构造函数中的参数,在定义属性时,则就需要一个默认值了
注意:init{} 要定义在 属性定义后, 否则会访问不到
 */
class Person8(val name: String) {
    var pName: String = name
    var pAge: Int = 0 //默认值
    init {
        pName = name
    }
    constructor(name: String, age: Int) : this(name) {
        pAge = age
    }
}

//其实所有主构造函数中的参数,都会被自动赋上一个默认值, 所以也可以手动指定一个默认值
private class Person9(val name: String = "")

/*
class 中可以有:
— Constructors and initializer blocks
— Functions
— Properties
— Nested and Inner Classes
— Object Declarations
 */

fun main(args: Array) {
    val per9 = Person9("stone")

    TT(3)
    TT(3, 4)
}
class TT {//没有在类名后定义主构造函数
    constructor(a: Int)
    constructor(a: Int, b:Int) : this(a)
}

 

inheritance


下面的代码示例了:

使用open, 表示可类被继承,表示函数、属性可被重写;
使用override 表示重写 函数、属性;
kotlin不能声明static的方法和属性;
abstract 声明抽象类与方法

package com.stone.clazzobj.inheritance


/**
 * desc  : 类的继承,方法重写
 * author: stone
 * email : aa86799@163.com
 * time  : 31/05/2017 16 32
 */

open class Base1 //使用open后 表示可被继承
class Derived1 constructor() : Base1() //继承时,用 : 表示继承关系,且需要表明父类的主构造函数

open class Base2(name: String)
class Derived2(fName: String) : Base2(fName)

//子类没有主构造函数,在内部其它构造函数,使用super 调用父类构造函数
open class Base3(name: String)
class Derived3 : Base3 {
    constructor(name: String) : super(name)
}

open class Base4 {
    open fun v() {}
    fun nv() {}
}
class Derived4() : Base4() {
     final override fun v() {}  //final 后  不可被再重写
//    override fun nv() {} //非open的fun 不能被重写
}

open class Foo1 {
    open val x: Int get() {return 1 + 3}
    /*open var x: Int get() {return x} set(value) {x = value}*/

    /*
    当声明了属性的get()后,就不会再自动生成对应的set方法了
    val 声明的属性 是不会有 set方法的, 因其不可变
    属性要被子类重写,也需声明时 加上 open
     */
}
class Bar1 : Foo1() {
    override var x: Int = 9
}

/*
如果有多个超类、接口,且它们定义了相同的成员,子类在重写时:
使用super 前缀 来标识
 */
open class A {
    open fun f() { print("A") } fun a() { print("a") }
}
interface B {
    fun f() { print("B") } // interface members are 'open' by default
    fun b() { print("b") }
}
class C() : A(), B {
// The compiler requires f() to be overridden:
    override fun f() {
        super.f() // call to A.f()
        super.f() // call to B.f()
    }
}

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

abstract class AbsDerived: AbsBase() {
//    override fun f() {} //直接重写
    override abstract fun f() //抽象重写,还是需要子类重写
}

class StableDerived : AbsDerived() {
    override fun f() {

    }
}

/*
Kt中不能声明static的方法和属性
 */

fun main(args: Array) {
    val d3 = Derived3("stone")

    val f1 = Foo1()
    println(f1.x)
//    f1.x = 1  //
    val b1 = Bar1()
    println(", ${b1.x}")
}

 

Properties


下面代码示例了:

const定义常量属性;
var定义的属性,可以重写get/set;
val定义的属性,仅能重写get;
field 关键字;
lateinit 定义延迟初始化的属性;

package com.stone.clazzobj.propertiesfields

//import kotlin.reflect.jvm.internal.impl.javax.inject.Inject

/**
 * desc  :
 * author: stone
 * email : [email protected]
 * time  : 01/06/2017 10 21
 */

//常量 必须定义在 Kotlin文件顶级, 不能定在 class或其它内部(在内部就是二级了)
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { }

class PropertiesOperation(size: Int) {

    val size = size

    //var 可变,可重写 get()、set()   仅指定get()时,需要进行初始化,指定默认值; set()为默认实现
    var stringRepresentation1: String = ""
        get() = this.toString()

    //var 重写 get()、set()
    var stringRepresentation2: String
        get() = this.toString()
        set(value) {
            setDataFromString(value) // parses the string and assigns values to other properties
        }

    private fun  setDataFromString(value: String) {}

    //val 不可变,只能重写 get()
    val isEmpty1: Boolean get() = this.size == 0
    val isEmpty2 get() = this.size == 0 // has type Boolean


    var setterVisibility: String = "abc"
        private set // the setter is private and has the default implementation
    var setterWithAnnotation: Any? = null
        /*@Inject*/ set // annotate the setter with Inject

    /*
    使用 field 关键字,指代它所在的属性。它仅能在 属性的 get或set中使用
    还有个比较形象的称呼:backing field。  向后看,就知它是指哪个属性了
     */
    var counter = 0 // the initializer value is written directly to the backing field
        set(value) {
            if (value >= 0) field = value
        }

    /*
    backing property
    使用一个私有属性 来实现当前属性的get、set
     */
    private var _table: Map? = null
    val table: Map
        get() {
            if (_table == null) {
                _table = HashMap() // Type parameters are inferred }
                return _table ?: throw AssertionError("Set to null by another thread")
            }
            return _table ?: throw AssertionError("Set to null by another thread")
        }


}

object Tes {//singleton

    //针对var 属性, 延迟初始化
    lateinit var str: String

    fun init(arg: String) {
        str = arg
    }


    //针对val 属性, 延迟加载
    val name: String by lazy {
        println("load name")
        "stone86"
    }
}


fun main(args: Array) {
    val gs = PropertiesOperation(3)
//    gs.setterVisibility = "" //set是private的 无法访问

    Tes.init("stone")
    println(Tes.str)
    println(Tes.name)

}

这里给出一个自定义View继承View时的实现

你可能感兴趣的:(Kotlin,学习Kotlin语言)