Kotlin入坑(五)类和继承二

Kotlin 中的接口跟java一样 使用 interface 定义

interface CallBack{
    fun result()
}

接口实现

class Child : CallBack{
    override fun result() {

    }
}

实现多个接口时,可能会遇到同一方法继承多个实现的问题。例如(官网的例子)两个接口定义的方法名字一样

interface A {
    fun foo() { print("A") }
    fun bar()
}

interface B {
    fun foo() { print("B") }
    fun bar() { print("bar") }
}

class C : A {
    override fun bar() { print("bar") }
}

class D : A, B {
    override fun foo() {
        super.foo()
        super.foo()
    }

    override fun bar() {
        super.bar()
    }
}

上面 A ,B中有相同的方法 D分别实现了A,B ,实现方法的时候,需要使用super 或者 super注明这个方法是哪个接口的

可见性修饰符

Kotlin 中有四个可见性修饰符:private、 protected、 internal 和 public。 如果没有显式指定修饰符的话,默认可见性是 public。

对于包的修饰

  • 如果不指定任何可见性修饰符,默认为 public,这意味着你的声明将随处可见;
  • private,跟java一样它只会在声明它的文件内可见;
  • internal,它会在相同模块(模块是:一个 IntelliJ IDEA 模块,一个 Maven 项目,一个 Gradle 源集,一次 <kotlinc> Ant 任务执行所编译的一套文件)内随处可见;
  • protected 不适用于顶层声明。

对于类和接口的修饰

  • private 意味着只在这个类内部(包含其所有成员)可见;
  • protected—— 和 private一样 + 在子类中可见;
  • internal —— 能见到类声明的 本模块内 的任何客户端都可见其 internal 成员;
  • public —— 能见到类声明的任何客户端都可见其 public 成员。

修饰构造函数 比如我们写单例的时候,一般吧构造函数私有化

class C private constructor(a: Int) { …… }

扩展函数

kotlin 支持函数的扩展 比如给一个String字符串加一个插入的方法

 fun String.insert(str:String) : String{
       var res = ""
       for (s in this){ //this代表的当前字符串
          res = res + s+ str
       }
       return res
   }

上面的方法给这个字符串每个字符中间插入另一个字符串就可以如下运用

 var string = "abcd"
 string = string.insert("e")
 Log.i("abcd",string)

结果就是每个字符中间加了一个e字符

12-14 11:20:41.969 28723-28723/com.chs.kotlintext I/abcd: aebecede

不止字符串,kotlin中可以对任何已经存在的对象进行扩展,比如 Array list,TextView……不需要继承,直接扩展方法。

数据类

我们经常创建一些只保存数据的类,比如我们的java bean 。json对应的实体类,在 Kotlin 中,这叫做 数据类 并标记为 data

data class User(val name: String, val age: Int)

泛型

kotlin中的泛型跟java类似

class Box<T>(t: T) {
    var value = t
}

val box: Box = Box(1)

如果类型参数可以推断出来,允许省略类型参数

val box = Box(1) 

kotlin中没有通配符类型,取而代之的是声明处型变(declaration-site variance)与类型投影(type projections)

kotlin泛型中的 in 关键字和 out关键字

  • in 修饰的泛型,只可以被消费而不可以被生产。只能用不能返回
  • out 修饰的泛型 是生产者,而不消费者。可以返回

泛型函数 , 类型参数要放在函数名称之前

fun  singletonList(item: T): List {
    // ……
}

fun  T.basicToString() : String {  // 扩展函数
    // ……
}

委托类 委托跟代理很类似啊

类 Derived 可以继承一个接口 Base,并将其所有共有的方法委托给一个指定的对象: 使用 by 关键字

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

class Derived(b: Base) : Base by b  //继承接口base 把方法实现委托给 Base的其他实现类

fun main(args: Array<String>) {
    val b = BaseImpl(10)
    Derived(b).print() // 输出 10
}

委托属性

class Example {
    var p: String by Delegate()
}

by 后面的表达式是该 委托 ,属性对应的 get()(和 set())会被委托给它的 getValue() 和 setValue() 方法

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name} in $thisRef.'")
    }
}

延迟属性 Lazy 接受一个 lambda 并返回一个 Lazy 实例的函数

val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}

fun main(args: Array<String>) {
    println(lazyValue)
    println(lazyValue)
}

输出

computed!
Hello
Hello

第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。默认情况下,对于 lazy 属性的求值是同步锁的(synchronized)

可观察属性 Observable

import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("") {
        prop, old, new ->
        println("$old -> $new")
    }
}

fun main(args: Array) {
    val user = User()
    user.name = "first"
    user.name = "second"
}
结果:
<no name> -> first
first -> second

每当我们给属性赋值时会调用该处理程序(在赋值后执行)。它有三个参数:被赋值的属性、旧值和新值

你可能感兴趣的:(Kotlin)