一般類形式:
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);
可以看出擴展之后,編寫代碼更加便捷了