Kotlin学习之路(4) 定义类与对象

终于到了Kotlin的核心篇章了,Kotlin的定义类,以及对象 接口 抽象类等等,这些知识点在Java中也是至关重要的

在这里插入图片描述

【定义类】

field

针对你定义的每一个属性,Kotlin都会产生一个field、一个getter、以及一个setter,field用来存储属性数据,你不能直接定义field, Kotin会封装field,保护它里面的数据,只暴露给getter和setter 使用。属性的getter方法决定你如何读取局性值,每个属性都有getter方法,setter方法决定你如何给属性赋值,所以只有可变属性才会有setter方法,尽管Kotin会自动提供默认的gete和seter方法,但在需要控制如何读写属性数据时,你也可以自定义他们。

class Player {
    
    var name = "abc"
        get() = field.capitalize()
        set(value) {
            field = value.trim()
        }
    
    var age = 10
    get() = field.absoluteValue
    private set(value) {
        field = value.absoluteValue
    }
}

初始化

在Player 类的定义头中定义一个主构造函数,使用临时变量为Player的各个属性提供初始值,在Kotlin中,便于识别 临时变量(包括仅引用一次的参数)通常都会以下划线开头的名字命名。

class Player(_name: String, _age: Int,_isNormal:Boolean ) {
   var name = _name
    get() = field.capitalize()
    private set(value) {
        field = value.trim()
    }

    var age = _age
    var isNormal = _isNormal
}

主构造函数里定义属性

Kotlin 允许你不使用临时变量赋值,而是直接用一个定义同时指定参数和类属性,通常我们更喜欢用这种方式定义类的属性,因为他会减少代码。

class Player(_name: String, var age: Int, val isNormal:Boolean ) {
   var name = _name
    get() = field.capitalize()
    private set(value) {
        field = value.trim()
    }
}

次构造函数

对应主构造函数的是次构造函数,我们可以定义多个次构造函数,来配置不同的参数组合。

constructor(name: String) : this(name, age = 20, isNormal = false)

默认参数

定义构造函数时,可以给构造函数参数指定默认值,如果用户调用时不提供值参,就使用这个默认值。

class PlayerOne(_name: String, var age: Int= 10, val isNormal:Boolean ) {
   var name = _name
    get() = field.capitalize()
    private set(value) {
        field = value.trim()
    }
}

初始化块

初始化块可以设置变量或者值,以及执行有效性检查,如检查给某个构造函数的值是否有效,初始化块代码会在构造类实例时执行。

    init {
        require(age > 10) { "age must be positive" }
        require(name.isNotBlank()) { "必须有个名字" }
    }

初始化顺序

主构造函数里声明的属性
类级别的属性赋值
init初始化块里的属性赋值和函数调用
次构造函数里的属性赋值和函数调用
在这里插入图片描述延迟初始化

使用lateinit关键字相当于做了一个约定:在用它之前负责初始化
只要无法确认lateinit变量是否完成初始化,可以执行isInitalized检测

class Player2 {
    lateinit var equipment:String
    fun ready(){
        equipment = "sharp  knife"
    }
    fun battle(){
        if (::equipment.isInitialized) println(equipment)
    }
}

惰性初始化

延迟初始化并不是推后初始化的唯一方式,你可以暂时不出初始化某个变量,直到首次使用它,这个叫做惰性初始化。

class Player3(_name: String) {
    var name = _name
    val config by lazy { loadConfig() }
    private fun loadConfig():String{
       return "loading"
    }
}

【继承】

Kotlin类默认都是封闭的,要让某个类开放继承,必须使用open关键字修饰它。

open class Animal(val name: String){

    fun MyName() = "名字是: $name"
    fun Eat() = "eat...."
}

class People :Animal("大卫")

函数重载

父类的函数也要以open关键字修饰,子类才能覆盖它。

类型转换

as操作符声明,这是一个类型转换

fun main() {
    val people = People()
    sale((people as Animal))
 }   

fun sale(p:Animal){
    p.Eat()
}

【对象】

objec 关键字

使用object关键字,你可以定义一个只能产生一个实例的类----单例
使用object关键字有三种方式
(1) 对象声明 (2) 对象表达式 (3) 伴生对象

伴生对象

如果你想将某个对象的初始化和实体类捆绑在一起,可以考虑伴生对象,使用companion修饰符,你可以在一个类定义里声明一个伴生对象,一个类只能有一个伴生对象。

open class ConfigMap{
    companion object{
        private const val Path = "sss"
        fun load()= File(Path).readBytes()
    }
}

嵌套类

如果一个类对另一个类有用,那么将其嵌入到该类中并使这两个类保持在一起合乎逻辑,可以使用嵌套类。

class Player2 {
   class Equipment(var name: String){
       fun show() =println("equipment $name")
   }
    fun battle(){
        Equipment("knife").show()
    }
}

数据类

数据类,是专门用来存储数据的类
数据类提供了toString的个性化实现
== 符号默认情况下,比较对象就是比较他们的引用值,数据提供了equals 和hasCode的个性化实现

fun main() {
    println(Coor(1,5))
   }
data class Coor(var x: Int, var y: Int) {
    //坐标是否为正数
    var isInBounds = x >= 0 && y >= 0
}

使用数据类的条件

数据类必须有至少带一个参数的主构造函数
数据类主构造函数的参数必须是val 或者var
数据类不能使用abstract open sealed 和 inner修饰符

运算符重载

操作符函数名作用
+plus把一个对象添加到另一个对象里
+=plusAssign把一个对象添加到另一个对象里,然后将结果赋值给第一个对象
>compareTo如果左面对象大于右面对象,返回true 否则返回false
[ ]get返回集合中指定的元素位置
rangeTo创建一个range对象
incontains如果对象在集合里返回true

【接口】

接口定义
Kotlin规定所有的接口属性和函数实现都要使用override关键字,接口定义的函数并不需要open关键字修饰,他们默认就是open.

interface Movable{
    var wheels:Int
    fun move(movable:Movable):String
}
class Car(_name: String,override var wheels:Int = 4):Movable{
    override fun move(movable: Movable): String {
        TODO("Not yet implemented")
    }
}

抽象类
要定义一个抽象类,需要在定义之前加上abstract关键字,除了具体的函数实现,抽象类也可以包含抽象函数一直有定义,没有函数实现。

abstract class Gun(val range: Int) {
    abstract fun trigger(): String
}
class AK47(_price:Int):Gun(range = 100){
    override fun trigger(): String  = "AK47 shooting"
}

核心点:定义类 接口 抽象类

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值