kotlin基础学习-5(对象,继承相关)

2022-04-15  本文已影响0人  ftd黑马
在main函数中调用
    //继承
    val carProduct : Product = CarProduct()
    println(carProduct.description())
    println(carProduct.load())

//继承
open class Product(val name : String){
    fun description () = "Product === $name"

    open fun load () = "Loading..."
}

//继承父类,父类必须用open关键字,否则默认类是final
class CarProduct:Product("aodi"){
    //这里的override是关键字,重写某父类方法需要加override,并且父类方法必须声明为open
    override fun load () ="aodi Loading..."

    fun carMethod() = "car special Method"
}
//类型转换
    println(carProduct is Product)
    println(carProduct is CarProduct)
    if(carProduct is CarProduct){
        println((carProduct as CarProduct).carMethod())
    }
//在kotlin中,声明一个类为单例很方便,直接使用object
object ApplicationConfig{
    init {
        println("applicationConfig init...")
    }

    fun doSomething(){
        println("doSomething")
    }
}

在main函数中调用
    //在kotlin中,声明一个类为单例很方便,直接使用object
    ApplicationConfig.doSomething()//这里并不是说是静态的,而是声明了是单例类,这里就可以直接使用类名作为对象名

    //指向的都是同一个对象,因为它是单例
    println(ApplicationConfig)
    println(ApplicationConfig)
    println(ApplicationConfig)

2.对象表达式

open class Player8 {
    open fun load() = "loading nothing"
}
在main函数中调用
    //对象表达式作为子类
    //类似于java中的new 一个OnclickListener,这个匿名类依然遵循object关键字的原则,一旦实例化,只能有唯一一个实例存在
    val p  = object : Player8(){
        override fun load() = "匿名类的loading方法"
    }
    println(p.load())

3.伴生对象

//伴生对象
open class SinggleTest{
    //只有初始化SinggleTest类或者调用load函数时,伴生对象的内容才会载入
    //而且无论实例化多少次,这个伴生对象始终只有一个实例存在。有点类似java的static
    //一个类里只能有一个伴生对象
    companion object{
        private const val PATH = "xxxxxxx"
        fun load() = println("伴生对象的方法执行")
    }
}
在main函数中调用
    //伴生对象
    SinggleTest.load()
//嵌套类(内部类)
//如果一个类只对另一个类有用,那么将其嵌入到该类中并使两个类保持在一起就很合逻辑,可以使用嵌套类
class Player1{
    class Equipment(var name:String){
        fun show() = println("equipment:$name")
    }
    fun battle() = println("ak47...")
}
在main函数中调用
    //嵌套类(内部类)
    Player1.Equipment("天空套").show()
/**
 * 使用数据类的条件
 *  对于那些经常需要比较,复制或打印自身内容的类,数据类很适用。然而,一个类要成为数据类,也要符合一定条件,总结下来,主要有三个方面
 *  1.数据类必须有至少带一个参数的主构造函数
 *  2.数据类主构造函数的参数必须是var 或者 val
 *  3.数据类不能使用abstract,open,sealed和inner修饰符
 */
//数据类,用data关键字修饰
data class Coordinate(val x : Int,val y : Int){
}

在main函数中调用
    //这里打印的是Coordinate(x=1, y=2)。如果不用data修饰,打印的是Coordinate@60e53b93
    println(Coordinate(1,2))

    //这里结果是true,如果类名不用data修饰,则是false
    println(Coordinate(1,2) == Coordinate(1,2))
//data数据类的copy函数demo
data class StudentOrigin(
    val name: String,
    var age : Int,
    var isNormal : Boolean
){
    var score = 0

    //次构造函数,有主就有次,我们可以定义多个次构造函数来配置不同的参数组合
    constructor(_name: String) : this (_name,age = 10,isNormal = false){
        //copy函数不会调用这,copy出去的值还是0
        score = 10
    }


    //初始化块,与java的static不一样,这里的初始化块是构造函数执行的时候,就会执行初始化快
    init {
        //先决函数,如果boolean值是false,执行lambda抛出异常
        require(age > 0) {
            "age must be positive"
        }
        require(name.isNotBlank()){
            "student must have a name"
        }
    }

    override fun toString(): String {
        return "StudentOrigin(name='$name', age=$age, isNormal=$isNormal, score=$score)"
    }
}
在main函数中调用
    //copy函数,它可以将数据类的其他属性都copy过来。但是这里有一个坑,次构造函数里面修改过的值不能copy,需要重新赋值
    val s = StudentOrigin("Jack")
    val copy = s.copy("Rose")
    println(s)
    println(copy)
//解构语法的demo类
class Demo(val x:Int , val y : Int){
    //这里的component1等名字都是固定写法,不能修改
    operator fun component1() = x
    operator fun component2() = y
}
//数据类,用data关键字修饰
data class Coordinate(val x : Int,val y : Int){
}

在main函数中调用
    //数据类默认支持解构语法,如果不是数据类,则需要我们手动在类里面重写方法,就如果解构语法demo类一样。
    val (x,y) = Coordinate(1,2)
    println("$x,$y")

    //解构语法的demo类
    val (a,b) = Demo(3,4)
    println("$a,$b")
/**
 * 运算符重载,常见的操作符
 *
 *
 *  操作符                 函数名                 作用
 *  +                     plus                  把一个对象添加到另一个对象里
 *  +=                    plusAssign            把一个对象添加到另一个对象里,然后将结果赋值给第一个对象
 *  ==                    equals                如果两个对象相等,则返回true,否则返回false
 *  >                     compareTo             如果左边的对象大于右边的对象,就返回true,否则返回false
 *  []                    get                   返回集合中指定位置的元素
 *  ..                    rangeTo               创建一个range对象
 *  in                    contains              如果对象包含在集合里,则返回true
 *
 */


data class Coordinate2(val x: Int,val y: Int){
    //运算符重载,使用operator关键字
    operator fun plus(other:Coordinate2) = Coordinate2(x+other.x,y+other.y)
}
在main函数中调用
    //运算符重载
    val coordinate2 = Coordinate2(10,50)
    val coordinate3 = Coordinate2(20,100)
    //如果下面的运算符不重写,这里使用+号就会报错
    println(coordinate2+coordinate3)
data class Coordinate2(val x: Int,val y: Int){
    //运算符重载,使用operator关键字
    operator fun plus(other:Coordinate2) = Coordinate2(x+other.x,y+other.y)
}

//枚举类,也可以定义函数
enum class Direction(val coordinate:Coordinate2){
    EAST(Coordinate2(1,2)),
    WEST(Coordinate2(3,4)),
    NORTH(Coordinate2(5,6)),
    SOUTH(Coordinate2(7,8));

    fun updateCoordinate(other: Coordinate2) = Coordinate2(
        other.x + coordinate.x,
        other.y + coordinate.y
    )
}
在main函数中调用
    //枚举类,用来定义常量集合的一种特殊类
    println(Direction.EAST) //输出的就是枚举的字符串值
    println(Direction.WEST.updateCoordinate(Coordinate2(10,20)))
//密封类demo
class Driver(var status: LicenseStatus){
    fun checkLicense () : String {
        return when(status){
            is LicenseStatus.Unqualified -> "没资格"
            is LicenseStatus.Learning -> "正在学"
            is LicenseStatus.Qualified -> "有资格,驾驶证编号: " + (this.status as LicenseStatus.Qualified).licenseId
        }
    }

}

//密封类
sealed class LicenseStatus{
    object Unqualified : LicenseStatus()                             //这里没有属性,所以把它定义为单例
    object Learning : LicenseStatus()                                //这里没有属性,所以把它定义为单例
    class Qualified (var licenseId:String) : LicenseStatus()         //这里有一个id的属性,所以不定义为单例
}
在main函数中调用
    println(Driver(LicenseStatus.Qualified("2820202")).checkLicense())
    println(Driver(LicenseStatus.Learning).checkLicense())
上一篇下一篇

猜你喜欢

热点阅读