一般类形式:
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);
可以看出扩展之后,编写代码更加便捷了