Kotlin學習-類(嵌套類,內部類,數據類,靜態類)及類擴展


一般類形式:

class Person(var name: String){//構造函數放在類頭部
    var age = 1
    var fulName: String
    var address = "china"

    init {//初始化模塊,與第一構造函數同時執行
        fulName = name+"_haha"
    }

    //類內部成員變量訪問通過get,set方法訪問
    //備用字段使用field聲明,field只能用於屬性的訪問器
    var lastName: String = "zhang"
        get() = field.toUpperCase()
        set//禁止修改

    //二級構造函數,需要加前綴 constructor:
    constructor (name: String, age:Int) : this(name) {
        //this.fulName = name
        this.age = age
    }

    var no: Int = 100
        get() = field  // 備用字段表示當前屬性,對當前字段值只能通過此field處理
        set(value) {  //變量修改方式
            if (value < 10) {
                field = value
            } else {
                field = -1
            }
        }

    var heiht: Float = 145.4f
        private set

    private fun selfMethod(){//私有方法
        println("self method ")
    }

    fun sayHello(){//無修飾符,默認public
        print("hello! nice to meet you!")
    }

    private val bar: Int = 1
    inner class MyInner{//內部類 in
        fun ff() = bar  // 訪問外部類成員
        fun innerTest() {
            var o = this@Person //獲取外部類的成員變量
            //內部類引用外部類成員
            println("name=${o.name}, age=${o.age}")
        }
    }

     class Nested {// 嵌套類
        fun foo() = "nest class content"
         fun myHandle(){
            println("Nested instance method invoke!")
         }
    }

}

 類訪問
 val p = Person("haha")
 p.address = "beijing"//set

嵌套類訪問
var pnest = Person.Nested()
pnest.foo()
內部類訪問
var pinner = Person("Tom").MyInner()// 內部類,Outter后邊有括號
pinner.innerTest()

 

匿名內部類:

kotlin object 對象表達式,相當於java匿名類

 fab.setOnTouchListener(object :View.OnTouchListener{//匿名類實現監聽器
        override fun onTouch(v: View?, event: MotionEvent?): Boolean {
            return false
        }
    })
//簡化為lambda表達式形式
fab2.setOnTouchListener { v , event ->
            if(event.action == MotionEvent.ACTION_UP){
                var pnest = Person.Nested()
                var str = pnest.foo()
                tvContent?.text = str
            }
            false
 }

 

靜態類,kotlin沒有靜態類,靜態方法,可以使用object修飾符替代 Java static功能

object SampleClass{
    var name: String = "jack tom"
    var no: Int = 101
    fun bar() {}
}

 訪問方式,

 SampleClass.name
 SampleClass.bar()

 

class SingletonSample2 private constructor() {
// 一個類里面只能聲明一個內部關聯對象,即關鍵字 companion 只能使用一次
    companion object {//通過companion object實現單例模式
        val instance = SingletonHolder.holder
		val tt:String = "static object"
    }

    private object SingletonHolder {
        val holder = SingletonSample2()
    }

    fun hello(){}
	
}

 

工廠模式實現:

interface Factory<T> {
    fun create(): T
}

class MyClass private constructor(){
    companion object : Factory<MyClass> {
        override fun create(): MyClass = MyClass()
    }
}

 

類屬性延遲初始化:

kotlin為確保類型安全,屬性在聲明和定義時需要指定屬性值,但對於想要延遲初始化或者開始無法確定時我們需要特殊處理,實現方式 lateinit關鍵字,layzy函數

class User(var name:String){
	//延遲初始化方式一
    lateinit var play:String //lateinit表示延遲初始化,若沒有初始化使用則拋出異常

    fun setUpValues(){
        play = "basketball"//String("football")
    }

    //延遲初始化方式二
    //lazy() 是一個函數, 接受一個 Lambda 表達式作為參數, 返回一個 Lazy <T> 實例的函數,
    // 返回的實例可以作為實現延遲屬性的委托
    val lazyValue: String by lazy {
        println("computed!")     // 第一次調用輸出,第二次調用不執行
        "Hello world"
    }
//   println(lazyValue)   // 第一次執行,執行lazy函數
//   println(lazyValue)   // 第二次執行,只輸出返回值 hello

    //延遲初始化方式三,Delegates屬性代理方式實現
    //notNull 適用於那些無法在初始化階段就確定屬性值的場合
    var notNullBar: String by Delegates.notNull<String>()
    //foo.notNullBar = "bar"
    //如果屬性在賦值前就被訪問的話則會拋出異常
    //println(foo.notNullBar)
	
    fun member(){ print("member method") }

}

 

繼承類, 接口

kotlin被繼承類必須使用open修飾,否則無法繼承

//open 修飾的類才能被繼承
open class BaseP(var name:String){  
    constructor(name:String,age:Int):this(name){
        println("-------base class construct init---------")
    }
    open fun getName(){ // open修飾方法,才允許子類重寫
        println("I'm base class")
    }

    fun getHello(){//普通方法無法重寫
        //......
    }
}

//子類繼承重寫方法
class Student:BaseP{
    constructor(name:String,age:Int,no:String,score:Int):super(name,age){
        println("-------construct init---------")
        println("name: ${name} age: ${age} num: ${no} score: ${score}")
    }

    override fun getName() {
        println("I'm student!")
    }
}

 

接口定義及實現:

//接口定義,接口內可以有非抽象方法或屬性
interface MyInterface {
    val prop: Int // abstract
    val name:String

    fun foo(){
        print("MyInterface foo")
    }
}

//接口實現
class MyImpl1:MyInterface{
    override val prop: Int
        get() = 18

    override val name: String
        get() = "james bond"

    override fun foo() {
//        super.foo()
        print("MyImpl1 foo method")
    }
}

多接口定義相同方法時,子類實現 對父類調用

interface IA {
    fun foo() {
        print( "A" )
    }

    fun bar()
}

interface IB {
    fun foo() {
        print( "B")
    }

    fun bar() {
        print("bar" )
    }
}

class D:IA,IB{
    override fun foo() {
        super<IA>.foo()//調用父類IA方法
        super<IB>.foo()//調用父類IB方法

    }

    override fun bar() {
        super<IB>.bar()
    }
}

 

類的擴展:

Kotlin 除了通過繼承,組合等還可以通過自身擴展特性對一個類的屬性和方法進行擴展,且不需要繼承
擴展是一種靜態行為,對被擴展的類代碼本身不會造成任何影響

class User(var name:String){

    fun member(){ print("member: ${name}") }
	
}

	//擴展函數
	fun User.printName(){
		print("name= $name")
	}
	//擴展函數和成員函數一致,則使用該函數時,會優先使用成員函數
	fun User.member(){
		print("add member!")
	}

擴展系統類函數

//Extension functions
fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' 代表當前擴展對象實例
    this[index1] = this[index2]
    this[index2] = tmp
}

 對一個類的擴展提高了靈活性,同時可以替換部分工具類

kotlin內有許多擴展實現,如文件擴展,這里實現了元Java FileUtil的功能

fun handle_file(fileName :String,fileContent :String,fileContentAsArray:ByteArray){
    File(fileName).writeText(fileContent)
    File(fileName).writeBytes(fileContentAsArray)

    File(fileName).printWriter().use { out -> out.println(fileContent) }
    File(fileName).bufferedWriter().use { out -> out.write(fileContent) }

//    Reads a file line by line
    File(fileName).forEachLine { println(it) }
    //read all lines
    File(fileName).bufferedReader().readLines()
    //we can convert that into bytes, and then into a complete String
    File(fileName).inputStream().readBytes().toString(Charsets.UTF_8)
    //Reads the entire content of the file as a String
    File(fileName).readText(Charsets.UTF_8)

    //手動調用文件寫操作
    val ft = File(fileName)
    ft.inputStream().use { input ->
        val result = ByteArray(1024*5)
        var offset = 0
        var remaining = ft.length().toInt()
        while (remaining > 0) {
            val read = input.read(result, offset, remaining)
            if (read < 0) break
            remaining -= read
            offset += read
        }
    }
    //file dir scan
    File("fdir").walkTopDown().forEach { println("${it.path}-isDir:${it.isDirectory}") }
    //file dir1 to dir2
    File("fcopySrcDir").copyRecursively(File("fcopyTarget"),overwrite = true)
    //file dir delete
    File("fdelSrcDir").deleteRecursively()

}

 

 

activity 擴展應用

fun <T : View> Activity.find(@IdRes id: Int): T {    
    return findViewById(id) as T
}


TextView label = find(R.id.label);
Button btn = find(R.id.btn);

 可以看出擴展之后,編寫代碼更加便捷了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM