• 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);
    

     可以看出扩展之后,编写代码更加便捷了

  • 相关阅读:
    struct&Method
    SetFinalizer、runtime.GC
    Map(没有写底层)
    数组和切片
    函数
    指针、Time
    字符串、strings、strconv
    基本类型和运算符
    第二阶段的事后诸葛亮
    第二个冲刺阶段第10天
  • 原文地址:https://www.cnblogs.com/happyxiaoyu02/p/10691388.html
Copyright © 2020-2023  润新知