Kotlin学习日记(五)类的多种多样

类有自己的一些特性,有些类有特有的功能,都是为了更好地解决问题。

枚举类

跟Java和其他语言的枚举类功能是一样的,可能用法和语法规则上有所不同。

enum class LogLevel(val id: Int){
    VERBOSE(0), DEBUG(1), INFO(2), WARN(3), ERROR(4), ASSERT(5);

    fun getTag(): String{
        return "$id, $name"
    }

    override fun toString(): String {
        return "$name, $ordinal"
    }
}

注解类

Kotlin的注解和Java差不多而且完全兼容。

声明注解类

annotation class 注解名

注解直接可以在类,函数,参数,变量,表达式,类型上等使用,一般起到了编译时检查和规范代码的作用。

内部类

在kotlin中也是有内部类的,总体上来说和java也差不多,但是有差别。

例子:

open class Outter{
    val a: Int = 0

    inner class Inner{
        val a: Int = 5

        fun hello(){
            println(this@Outter.a)
        }
    }

}

interface OnClickListener{
    fun onClick()
}

class View{
    var onClickListener: OnClickListener? = null
}

fun main(args: Array<String>) {
    val inner = Outter().Inner()

    val view = View()
    view.onClickListener = object : Outter(), OnClickListener{
        override fun onClick() {

        }
    }
}

内部类,添加关键字inner,这样就可以访问外部类的成员。

在内部类里面的成员和外部成员有相同的属性名的时候,可以使用一下这种方式调用来区分外部类和内部类:

println(this@Outter.a)

匿名内部类

在android里面这个东西一定不陌生,匿名内部类都是通过对象表达式创建的:

val view = View()
    view.onClickListener = object : Outter(), OnClickListener{
        override fun onClick() {

        }
    }

但是object:Outter(),onClickListener{}这行代码有点迷,实际上java和kotlin的匿名内部类的区别在这,kotlin的匿名内部类像不同的类一样,允许继承,java不行。

object

有些时候特定的这类事物只能有一个,比如只能有一个老婆,这要是多了,这天天的得多热闹。(๑•ᴗ•๑)

Kotlin中没有静态属性和方法,但是也提供了类似单里的功能,就是object这么个东西。

object AdminUser {
    val username: String = "admin"
    val password: String = "admin"
    fun getTimestamp() = SimpleDateFormat("yyyyMMddHHmmss").format(Date())
    fun md5Password() = EncoderByMd5(password + getTimestamp())
}

就这样一个简单的单例就写好了。

object可以在内部类与匿名内部类中使用。

伴生对象

kotlin中提供了伴生对象 ,用companion object关键字声明:

fun main(args: Array<String>) {
    val latitude = Latitude.ofDouble(3.0)
    val latitude2 = Latitude.ofLatitude(latitude)

    println(Latitude.TAG)
}

class Latitude private constructor(val value: Double){
    companion object{
        @JvmStatic
        fun ofDouble(double: Double): Latitude{
            return Latitude(double)
        }

        fun ofLatitude(latitude: Latitude): Latitude{
            return Latitude(latitude.value)
        }

        @JvmField
        val TAG: String = "Latitude"
    }
}

很像是java里面的静态方法,实际上只是想,并不是一样的,kotlin是与java完全兼容的,那么在java中如何调用ofDouble()方法和属性TAG呢?就像例子中的加了一个注解@JvmStatic @JvmField

sealed密封类

就像我们为什么要用enum类型一样,比如你有一个enum类型 MoneyUnit,定义了元、角、分这些单位。枚举就是为了控制住你所有要的情况是正确的,而不是用硬编码方式写成字符串“元”,“角”,“分”。

同样,sealed的目的类似,一个类之所以设计成sealed,就是为了限制类的继承结构,将一个值限制在有限集中的类型中,而不能有任何其他的类型。

在某种意义上,sealed类是枚举类的扩展:枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。

要声明一个密封类,需要在类名前面添加 sealed 修饰符。密封类的所有子类都必须与密封类在同一个文件中声明(在 Kotlin 1.1 之前, 该规则更加严格:子类必须嵌套在密封类声明的内部):

sealed class Expression

class Unit : Expression()
data class Const(val number: Double) : Expression()
data class Sum(val e1: Expression, val e2: Expression) : Expression()
data class Multiply(val e1: Expression, val e2: Expression) : Expression()
object NaN : Expression()

使用密封类的主要场景是在使用 when 表达式的时候,能够验证语句覆盖了所有情况,而无需再添加一个 else 子句:

fun eval(expr: Expression): Double = when (expr) {
    is Unit -> 1.0
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    is Multiply -> eval(expr.e1) * eval(expr.e2)
    NaN -> Double.NaN
// 不再需要 `else` 子句,因为我们已经覆盖了所有的情况
}
//测试代码:
fun main(args: Array<String>) {
    val u = eval(Unit())
    val a = eval(Const(1.1))
    val b = eval(Sum(Const(1.0), Const(9.0)))
    val c = eval(Multiply(Const(10.0), Const(10.0)))
    println(u)
    println(a)
    println(b)
    println(c)
}
输出:
1.0
1.1
10.0
100.0

data数据类

在 Kotlin 中,也有对应这样的领域实体类的概念,并在语言层面上做了支持,叫做数据类,相当于javaBean:

data class Book(val name: String)
data class Fook(var name: String)
data class User(
        val name: String,
        val gender: String,
        val age: Int
) {
    fun validate(): Boolean {
        return true
    }
}

这里的var/val是必须要带上的。因为编译器要把主构造函数中声明的所有属性,自动生成以下函数:

equals()/hashCode() 
toString() : 格式是 User(name=Jacky, gender=Male, age=10)
componentN() 函数 : 按声明顺序对应于所有属性component1()、component2() ...
copy() 函数

具体看文档吧,这里东西比较多。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值