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