五分钟学习kotlin-基本特性

关键字

lateinit :延迟初始化

    lateinit var a : String
    a = "hello"
    println(" lateinit a = $a");

单一抽象方法,可以使用lambda表达式,无需重写方法,直接在大括号中写对应的实现即可。

​
fun interface SayHello{
    fun say(str:String):String
}
fun testSam(){
    //普通写法
    var str = object : SayHello {
        override fun say(str: String): String {
            println("$str")
            return str;
        }
    }
    //lambda 表达式写法
    var str2 = SayHello {
        println("$it")
        return@SayHello it;
    }
    str.say("你好")
    str2.say("kotlin")
}

拓展函数:直接给一个类后面增加点号和一个函数,就能够在别的地方进行调用这个函数。

拓展函数不会修改原来的类,只是通过点号表达式去调用这个方法。调用拓展函数只取决于函数调用时表达式的类型来决定。

如果成员函数和扩展函数相同,那么优先调用成员函数。

fun MutableList .swap(i1:Int,i2:Int){
    val tmp  = this[i1];
    this[i1] = this[i2];
    this[i2] = tmp;
}
fun testExpand(){
    val list = mutableListOf(1,2,3,4)
    list.swap(0,3);
    println(list)
}
​
​
open class Shape
class Rectangle: Shape()
fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Rectangle"
fun printClassName(s: Shape) {
    println(s.getName())
}    
printClassName(Rectangle())//会打印 Shape,因为调佣扩展函数时,类型时shape

扩展属性:可以一个类增加属性。但是并没有改变原来的类,只是可以通过点号计算对应的属性。只能显示提供setter、getter,而不能使用构造器。

val  List.lastIndext:Int
    get()= size-1;
var list = listOf(11,2,3,4,54)
println(list.lastIndext)

伴生对象也可以使用扩展函数和扩展属性。

class MyClass {
    companion object { }  // 将被称为 "Companion"
}
fun MyClass.Companion.printCompanion() { println("companion") }
​
fun main() {
    MyClass.printCompanion()
}

扩展函数的作用域在当前包里面,如果在其他包里需要引用

package org.example.declarations
fun List.getLongestString() { /*……*/}
​
package org.example.usage
import org.example.declarations.getLongestString
fun main() {
    val list = listOf("red", "green", "blue")
    list.getLongestString()
}

扩展声明为成员

声明为成员的扩展可以声明为 open 并在子类中覆盖。这意味着这些函数的分发对于分发接收者类型是虚拟的,但对于扩展接收者类型是静态的。

open class Base { }
​
class Derived : Base() { }
​
open class BaseCaller {
    open fun Base.printFunctionInfo() {
        println("Base extension function in BaseCaller")
    }
​
    open fun Derived.printFunctionInfo() {
        println("Derived extension function in BaseCaller")
    }
​
    fun call(b: Base) {
        b.printFunctionInfo()   // 调用扩展函数
    }
}
​
class DerivedCaller: BaseCaller() {
    override fun Base.printFunctionInfo() {
        println("Base extension function in DerivedCaller")
    }
​
    override fun Derived.printFunctionInfo() {
        println("Derived extension function in DerivedCaller")
    }
}
​
fun main() {
    BaseCaller().call(Base())   // “Base extension function in BaseCaller”
    DerivedCaller().call(Base())  // “Base extension function in DerivedCaller”——分发接收者虚拟解析
    DerivedCaller().call(Derived())  // “Base extension function in DerivedCaller”——扩展接收者静态解析
}

密封类:要声明一个密封类,需要在类名前面添加 sealed 修饰符。虽然密封类也可以有子类,但是所有子类都必须在与密封类自身相同的文件中声明,密封类是抽象的,不能实例化,密封类的间接继承者可以不用在一个文件里面。

sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

密封列比较好使用when表达式

fun eval(expr: Expr): Double = when(expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
    // 不再需要 `else` 子句,因为我们已经覆盖了所有的情况
}

类型投影:Array对应于 Java 的Array<? super String>

声明处型变:Array对应于 Java 的 Array<? extends Object>

内部类:

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

匿名内部类

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

枚举

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}
enum class Color(val rgb: Int) {
        RED(0xFF0000),
        GREEN(0x00FF00),
        BLUE(0x0000FF)
}

伴生对象:

类内部的对象声明可以用 companion 关键字标记:该伴生对象的成员可通过只使用类名作为限定符来调用.可以省略伴生对象的名称,在这种情况下将使用名称 Companion即使伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员

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

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

val instance = MyClass.create()
class MyClass {
    companion object { }
}

val x = MyClass.Companion

内联类 的特殊类,它通过在类的前面定义一个 inline 修饰符来声明,内联类必须含有唯一的一个属性在主构造函数中初始化.

委托:委托模式已经证明是实现继承的一个很好的替代方式, 而 Kotlin 可以零样板代码地原生支持它。

interface Base {
    fun print()
}
class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun main() {
    val b = BaseImpl(10)
    Derived(b).print()
}

Derived 的超类型列表中的 by-子句表示 b 将会在 Derived 中内部存储, 并且编译器将生成转发给 b 的所有 Base 的方法。委托对象的成员只能访问其自身对接口成员实现.

属性委托:属性的委托不必实现任何的接口,但是需要提供一个 getValue() 函数(与 setValue()——对于 var 属性)

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

标准委托

  • lazy()是接受一个 lambda 并返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托

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

fun main() {
    println(lazyValue)
    println(lazyValue)
}
  • Delegates.observable() 接受两个参数:初始值与修改时处理程序(handler)。 每当我们给属性赋值时会调用该处理程序(在赋值执行)。它有三个参数:被赋值的属性、旧值与新值

    class User {
        var name: String by Delegates.observable("") {
            prop, old, new ->
            println("$old -> $new")
        }
    }
    fun main() {
        val user = User()
        user.name = "first"
        user.name = "second"
    }

    委托给另一个属性:为将一个属性委托给另一个属性,应在委托名称中使用恰当的 :: 限定符,例如,this::delegateMyClass::delegate

    class MyClass(var memberInt: Int, val anotherClassInstance: ClassWithDelegate) {
        var delegatedToMember: Int by this::memberInt
        var delegatedToTopLevel: Int by ::topLevelInt
        
        val delegatedToAnotherClass: Int by anotherClassInstance::anotherClassInt
    }
    var MyClass.extDelegated: Int by ::topLevelInt

    局部函数:Kotlin 支持局部函数,即一个函数在另一个函数内部,局部函数可以访问外部函数(即闭包)的局部变量,所以在上例中,visited 可以是局部变量

    fun dfs(graph: Graph) {
        val visited = HashSet()
        fun dfs(current: Vertex) {
            if (!visited.add(current)) return
            for (v in current.neighbors)
                dfs(v)
        }
    
        dfs(graph.vertices[0])
    }

    高阶函数:高阶函数是将函数用作参数或返回值的函数。

    集合:使用的时候再来查。

    内置函数let、also、with、run、apply

    let 可以使用it代替当前队形,并且返回最后一行表达式结果。

    also 可以使用it代替当前对象,返回当前对象。

    with 调用对象的时候省略对象名称, 返回最后一行表达式。

    run 可以直接调用方法、属性。返回最后一行表达式。

    apply 直接调用属性和方法,返回对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值