重学Kotlin(四) 类与对象

数据类

我们经常创建一些只保存数据的类。 在 Kotlin 中,这叫做 数据类 并标记为 data:

//如果生成的类需要含有一个无参的构造函数,则所有的属性必须指定默认值。
data class User(val name: String = "", val age: Int = 0)

主构造函数内部定义的属性会自动生成一些函数(equals()/hashCode()
toString()等)。
如需在生成的实现中排除一个属性,请将其声明在类体中:

//在 toString()、 equals()、 hashCode() 以及 copy() 的实现中只会用到 name 属性
data class Person(val name: String) {
//不会自动生成data的相关函数
    var age: Int = 0
}

copy() 函数实现复制一个对象改变它的一些属性,但其余部分保持不变。

val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)

密封类

sealed 关键字开头的类
使用密封类的关键好处在于使用 when 表达式 的时候,如果能够验证语句覆盖了所有情况

sealed class MyColor {
    class Yellow : MyColor()
 
    class Red : MyColor()
 
    class Black : MyColor()
}
 
fun evals(color: MyColor) =
   when (color) {
    is MyColor.Yellow -> println("yellow")
    is MyColor.Red -> println("red")
    is MyColor.Black -> println("black")
}//不需要使用else了
 
fun main(args: Array<String>) {
    evals(MyColor.Black())
}

嵌套类与内部类

标记为 inner 的嵌套类为内部类,能够访问其外部类的成员。
内部类会带有一个对外部类的对象的引用:

class Outer {
    private val bar: Int = 1
    //无inner为嵌套类
    inner class Inner {
        fun foo() = bar
    }
}

val demo = Outer().Inner().foo() // == 1

匿名内部类
使用对象表达式创建匿名内部类实例:

window.addMouseListener(object : MouseAdapter() {

    override fun mouseClicked(e: MouseEvent) { …… }

    override fun mouseEntered(e: MouseEvent) { …… }
})

枚举类

枚举类的最基本的用法是实现类型安全的枚举:

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}
//通过名称获取枚举常量
EnumClass.valueOf(value: String): EnumClass
//获取所有枚举常量
EnumClass.values(): Array<EnumClass>

内联类

在使用包装类的场景可以考虑使用内联类实现,它可以提升包装类的性能。
什么是包装类?
基本数据类型 —>包装类
boolean —> Boolean
char —> Character
byte—> Byte
short—> Short
long
Long
int —> Integer
float—> Float
double—> Double
右边的开头大写字母的就是包装类

通过inline 关键字来定义内联类

//内联类必须含有唯一的一个属性在主构造函数中初始化
inline class Password(val value: String)

对象表达式

要创建一个继承某个类型的匿名类的对象,我们会这么写:

window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) { /*……*/ }

    override fun mouseEntered(e: MouseEvent) { /*……*/ }
})

或者这样

class C {
    // 私有函数,所以其返回类型是匿名对象类型
    private fun foo() = object {
        val x: String = "x"
    }

    // 公有函数,所以其返回类型是 Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // 没问题
        val x2 = publicFoo().x  // 错误:未能解析的引用“x”
    }
}

Kotlin中的单例模式

object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
        // ……
    }

    val allDataProviders: Collection<DataProvider>
        get() = // ……
}

对象声明的初始化过程是线程安全的并且在首次访问时进行。

如需引用该对象,我们直接使用其名称即可:

DataProviderManager.registerDataProvider(……)

伴生对象可以用 companion 关键字标记:

class MyClass {
//也可以给伴生对象命名 Factory 
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}
//使用:
val instance = MyClass.create()
或者
val instance = MyClass.Factory.create()

伴生对象实现接口:

interface Factory<T> {
    fun create(): T
}

class MyClass {
    companion object : Factory<MyClass> {
        override fun create(): MyClass = MyClass()
    }
}

val f: Factory<MyClass> = MyClass

在 JVM 平台,如果使用 @JvmStatic 注解,你可以将伴生对象的成员生成为真正的静态方法和字段

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哆啦A梦z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值