Kotlin笔记(三)

构造方法

fun main() {
    //次构造方法创建对象
    val student = Student()
    println(student.toString())
    student.age = 23
    student.name = "jim"
    student.flag = true
    println(student.toString())
    //主构造方法创建对象
    val student2 = Student("main", 18, true)
    println(student2.toString())
    //具名主构造函数创建对象(需要少传的参数提前给好默认值)
    val student3 = Student("main20", flag = true)
    println(student3.toString())
    //初始化代码块发现年龄小于等于0时抛出异常
    val student4 = Student("age0", -1, false)
    println(student4.toString())
}

//主构构造方法 构造方法中可以直接设置成员变量,系统自动为其生成get和set方法
//只使用一次的临时变量前面加_
//代码初始化执行顺序:1主构造函数赋值,2类中成员变量赋值和初始化代码块运行取决于谁写在前面,3次构造函数运行
class Student(_name:String, var age:Int = 20, var flag:Boolean) {
    //自定义get set方法
    var name:String? = _name
        get() = field?.toUpperCase()
        set(value) {
            field = "姓名:$value"
        }

    //次构造方法
    constructor() : this("AaA", 22, false){
        //TODO 次构造方法中初始化
    }

    //初始化代码块,构造函数调用时调用
    //初始代码块若要使用类中成员的变量,必须把使用类中成员变量的赋值写在初始代码块上面
    init {
        require(age > 0) {"年龄不能小于等于0"}
    }

    override fun toString(): String {
        return "姓名:${name},年龄${age},标识:${flag}"
    }

    //延迟初始化属性使用关键字lateinit,使用前需要手动初始化才能使用
    lateinit var late:String
    fun initLate() {
        late = "late"
    }
    fun useLate() {
        //判断是否被初始化,不判断未初始化会报UninitializedPropertyAccessException
        if (::late.isInitialized){
            println(late)
        }
    }

    //惰性初始化属性使用关键字by lazy,表示第一次使用时自动初始化为后面的值
    val config by lazy {"config"}
}

继承

fun main() {
    val a = A()
    //B构造时构造方法与A的次级构造相同,所以走父类次级构造方法
    val b:A = B()
    //is判断关键字进行类型判断
    println(a is A)//true
    println(a is B)//false
    println(a is File)//false
    println(b is A)//true
    println(b is B)//true
    println(b is File)//false
    //as关键字进行向下类型转换
    (b as B).inputChild()
    //kotlin智能类型转换,只要前面转换成功,后续使用该对象可以不用转换直接使用
    b.inputChild()

    //Any是所有类的父类,相当于java的Object
    //与Object不同的是Any中并不能直接看到方法的实现,方法会根据不同的环境变换实现内容,比java跨平台性更强大
    println(a is Any)
}

//kotlin默认都是不可继承的,用open关键字表示可继承
open class A(open var name:String) {

    constructor() : this("p") {
        input()
    }

    open fun input() = println("Parent,${name}")

}

class B : A() {
    //override关键字表示重写父类方法
    override fun input() = println("Child,${name}")

    fun inputChild() = println("only child can use")
}

object关键字

fun main() {
    val s1 = Single
    val s2 = Single
    println(s1 === s2)//true
    //调用方法直接使用类名
    Single.pri()

    //生成一个单例类型的SingleP匿名子类
    val c = object : SingleP() {
        override fun pri() {
            println("SingleC")
        }
    }
    c.pri()

    //伴生对象调用
    SingleComp.load()
    SingleComp.path = "path2"
    SingleComp.load()
}

//object修饰的为单例对象,不可有构造方法
object Single {

    fun pri() {
        println("Single")
    }

}

open class SingleP {
    open fun pri() {
        println("SingleP")
    }
}

class SingleComp {
    //kotlin中没有static关键字
    //companion object表示类中的伴生对象,只有外界调用时才会加载进内存,且内存中一直保持为一份
    companion object {
        private const val CONFIG = "config"
        var path = "path"
        fun load() = println(CONFIG + path)
    }

}

嵌套类

fun main() {
    Outer().outer()
    //和java不一样,kotlin可以外部类可以用类名直接创建内部类并进行调用方法
    Outer.Inner().inner()
}

class Outer {

    class Inner {
        fun inner() = println("Inner")
    }

    fun outer() = println("Outer")
}

数据类

fun main() {
    println(WH(1, 2))//打印内存地址
    //数据类系统默认重写了toString方法打印数据内容
    println(XY(1, 2))//打印数据内容
    //==比较的是equals
    println(WH(1, 2) == WH(1, 2))
    //数据类重写了equals方法和hashCode方法
    println(XY(1, 2) == XY(1, 2))

    val xy = XY(1)
    //copy函数拷贝数据类,拷贝过程不走次构造函数,只拷贝主构造函数的数据
    val xyC = xy.copy(x = 50)
    println(xy)//x=1,y=888,z=999
    println(xyC)//x=50,y=888,z=10

    //普通类实现解构语法
    val(a, b) = WH(2, 3)
    println("a=${a},b=${b}")
    //数据类中自动生成解构语法声明,可直接使用
    val(c, d) = XY(10, 20)
    println("c=${c},d=${d}")

    //使用运算符重载
    println(XY(11, 22) + XY(33, 55))
}

//普通类
class WH(var w:Int, var h:Int) {
    //普通类实现解构语法需要先声明
    operator fun component1() = w
    operator fun component2() = h
}


//数据类使用data关键字
//需要比较,复制打印自身内容的时候使用数据类比较好
//数据类必须有至少带一个参数的主构造函数,且主构造函数参数必须用val和var修饰
//数据类不能用abstract,open,sealed,inner修饰
data class XY(var x:Int, var y:Int) {

    var z:Int = 10

    constructor(_x:Int) : this(_x, 2) {
        z = 999
        y = 888
        println("次构造函数")
    }

    //运算符重载
    //+ plus
    //+= plusAssign
    //== equals
    //> compareTo
    //[] get
    //.. rangeTo
    //in contains
    operator fun plus(other:XY) = XY(other.x + x, other.y + y)

    override fun toString(): String {
        return "x=${x},y=${y},z=${z}"
    }
}

枚举

fun main() {
    println(Direction.EAST)
    //枚举元素就是枚举类的一个实例对象
    println(Direction.EAST is Direction)
    //枚举中方法使用
    println(Direction.WEST.getXY(XY(12, 14)))

    //枚举配合选择语句使用
    val dir = Direction.NORTH
    println(when(dir) {
        Direction.EAST -> "东"
        Direction.WEST -> "西"
        Direction.SOUTH -> "南"
        Direction.NORTH -> "北"
    })
}

//枚举中可以有方法,枚举对象可以有构造属性
enum class Direction(private val xy:XY) {
    EAST(XY(1, 1)),
    WEST(XY(2, 2)),
    SOUTH(XY(3, 3)),
    NORTH(XY(4, 4));

    fun getXY(pXY:XY) = XY(pXY.x + xy.x, pXY.y + xy.y)
}

密封类

fun main() {
    val abc:ABC = when((1..3).random()) {
        1 -> ABC.A
        2 -> ABC.B
        3 -> ABC.C("ccc")
        else -> ABC.A
    }
    println(when(abc){
        is ABC.A -> "a"
        is ABC.B -> "b"
        is ABC.C -> (abc as ABC.C).cId
    })
}

//密封类,类似枚举的实现,包含一系类继承自己的子类
sealed class ABC {
    //没有属性的子类使用单例节省内存
    object A : ABC()
    object B : ABC()
    //有属性的子类使用class做出区分
    class C(val cId:String) : ABC()
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值