美文网首页
Kotlin入坑基础篇一

Kotlin入坑基础篇一

作者: My_Hubery | 来源:发表于2018-08-01 14:21 被阅读0次

    Kotlin入坑的理由:

    1,大大减少Java样板代码;
    2,避免空指针异常等;
    3,充分利用JVM,Android现有的库,和JAVA可以完全兼容;
    4,Google推荐为Android开发的首选;
    5,编译器的良好支持。

    我们现在在新功能或者新项目中使用kotlin语言,而旧的项目只需要简单的维护的则继续使用java语言。不管怎样,你都可以尝试使用kotlin去编程。

    Kotlin的使用

    函数

    函数定义使用关键字 fun,参数格式为:参数 : 类型

    /**
     * 计算两个数的差,返回类型为Int
     */
    fun testSub(a: Int, b: Int): Int {
        return a - b
    }
    

    kotlin语言默认支持lambda表达式

    // 使用lambda表达式
    fun testLambda() {
        val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
        println(sumLambda(1,2))  // 输出 3
    }
    

    变长参数测试

     fun testVararg(vararg v:Int){
            for(vt in v){
                print(vt)
            }
        }
        
        fun testVar(){
            testVararg(1,2,3)
        }
    

    此外,kotlin还提供了便捷的字符串模板

    /**
     * 字符串模板
     */
    fun testTemp() {
        val s = "kotlin"
        val curStr = "我正在使用$s"
        print(curStr)
    }
    

    打印出来是”我正在使用kotlin“,可以省去java的字符串拼接;
    通过上面的例子发现kotlin省略了;号的结束符号,此外kotlin定义字段的时候,只有varval两个修饰符,var表示可变变量定义,val表示不可变变量定义和Java中的final修饰的变量类似,并且kotlin可以声明变量的时候不指定变量类型,由编译器自动推断。

    循环(for和while)

    /**
     * for循环
     */
    fun testFor() {
        for (i in 1..4) {
            print(i)
        }
    
        for (i in 1..4 step 2) {
            print(i)
        }
    
        //对集合进行迭代
        val items = listOf("apple", "banana", "kiwi")
        for(item in items){
            println(item)
        }
    
        for(index in items.indices){
            println("item at $index is ${items[index]}")
        }
    
    }
    
    /**
    * 使用两种while遍历
    */
    fun testWhile() {
        var x = 5
        while (x > 0) {
            println( x--)
        }
    
        var y = 5
        do {
            println(y--)
        } while(y>0)
    }
    

    条件语句(if和when)

    值得注意的是kotlin中并没有swith语句,而使用了when替代;

    /**
     * when 将它的参数和所有的分支条件顺序比较,直到某个分支满足条件。
     * 类似于switch
     */
    fun testWhen(x: Int) {
          when (x) {
            is Int -> print(x.toString())
            else -> {
                print("不是int类型")
            }
        }
    }
    

    一个 if 语句包含一个布尔表达式和一条或多条语句。
    kotlin中使用以下的表达式来替换java中的三元操作符:

    // 作为表达式
    val max = if (a > b) a else b
    

    使用 in 运算符来检测某个数字是否在指定区间内

    /**
    * 使用区间
    */
    fun testIf() {
        val x = 5
        if (x in 1..8) {
            println("x 在区间内")
        }
    }
    

    Kotlin中的对象和类

    Kotlin中的类都是继承Any类(注意:并不是Object),它是所有类的超类,对于没有超类型声明的类是默认超类,Kotlin中与Java相同只能使用单继承。constructor为构造函数,init函数里面可以进行初始化操作。

    class Person constructor(firstName: String) {
        init {
            println("FirstName is $firstName")
        }
    }
    

    下面来看看对象和类的使用

    /**
     * 接口里面的成员变量默认为open类型
     * kotlin接口与java 8类似,可以在接口里面实现方法
     */
    interface TestInterface {
        fun test() {
            print("TestInterface接口中的test()调用")
        }
    }
    
    /**
     * 类属性修饰符
     * abstract    // 抽象类
     * final       // 类不可继承,默认属性
     * enum        // 枚举类
     * open        // 类可继承,类默认是final的
     * annotation  // 注解类
     *
     * 访问权限修饰符
     * private    // 仅在同一个文件中可见
     * public     // 所有调用的地方都可见
     * internal   // 同一个模块中可见
     *  没有显式定义访问修饰符,默认为“public ”,对所有可见。
     */
    open class Outer {
        private val bar: Int = 1
        private val name: String = "123456"
    
        class Nested {
            fun foo(): String {
                val curString: String = "123"
                return curString
            }
        }
    
        inner class Inner {
            fun innerTest(): String {
                return this@Outer.name
            }
        }
    
        open fun setInterface(test: TestInterface) {
            test.test()
        }
    
        open fun test() {
    
        }
    }
    
    /**
     * Kotlin也只能单继承
     */
    class OuterImpl : Outer(), TestInterface {
        /**
         * 如果继承和实现的方法中,有同样的test方式,需要这样调用父类或者接口的方法
         * 另外:属性重写使用 override 关键字,属性必须具有兼容类型,每一个声明的属性都可以通过初始化程序或者getter方法被重写
         * 你可以用一个var属性重写一个val属性,但是反过来不行。因为val属性本身定义了getter方法,重写为var属性会在衍生类中额外声明一个setter方法
         */
        override fun test() {
            super<Outer>.test()
            super<TestInterface>.test()
        }
    
        override fun setInterface(test: TestInterface) {
            super.setInterface(test)
        }
    }
    
    /**
     * 测试
     */
    fun testOuter(): String {
        var curStr = Outer.Nested().foo()// 调用格式:外部类.嵌套类.嵌套类方法/属性
        val curName = Outer().Inner().innerTest()//调用内部类
        //匿名内部类
        Outer().setInterface(object : TestInterface {
            override fun test() {
                print("这里是一个匿名内部类")
            }
        })
        OuterImpl().setInterface(object : TestInterface {
            override fun test() {
                print("这里使用了继承实现匿名内部类")
            }
        })
        return "Outer.Nested().foo()中的curString=${Outer.Nested().foo()}   Outer().Inner().innerTest()中name=$curName"
    }
    

    var curStr = Outer.Nested().foo()// 调用格式:外部类.嵌套类.嵌套类方法/属性
    val curName = Outer().Inner().innerTest()//调用内部类
    值得注意的是以上调用方式的不同。

    Kotlin接口

    Kotlin 接口与 Java 8 类似,使用 interface 关键字定义接口,允许方法有默认实现:

    interface CustomInterface {
        fun testOne()    // 未实现
        fun testTwo() {  //已实现
          // 可选的方法体
          println("testTwo()")
        }
    }
    

    接口中的属性只能是抽象的,不允许初始化值,接口不会保存属性值,实现接口时,必须重写属性

    interface CustomInterface{
        var name:String //name 属性, 抽象的
    }
     
    class CustomImpl:CustomInterface{
        override var name: String = "Hubery" //重载属性
    }
    
    伴生对象

    类内部的对象声明可以用 companion 关键字标记,这样它就与外部类关联在一起,我们就可以直接通过外部类访问到对象的内部元素。另外一个类里面只能够有一个伴生对象,也就是只能有一个companion修饰符。

    java中我们常常使用static,而kotlin里面没有这个而使用伴生对象替代。不过并不完全相等。

    companion object {
            val EXTRA_ORDER_ID = "order_id"
    }
    

    类似于Java中如下定义 :

    public static final String EXTRA_ORDER_ID = "extra_order_id";
    

    需要注意的是:在kotlin语言中別的类需要访问就直接 类名.字段名访问就行,而在java中调用kotlin的EXTRA_ORDER_ID,在这里就需要使用
    类名.Companion.getEXTRA_ORDER_ID()

    伴生对象的成员看起来像其他语言的静态成员,但在运行时他们仍然是真实对象的实例成员。比如还可以实现接口:

    interface CustomInterface<T> {
        fun create(): T
    }
    class DemoClass {
        companion object : CustomInterface<DemoClass > {
            override fun create(): DemoClass = DemoClass ()
        }
    }
    
    数据类和密封类
    数据类

    kotlin使用data来修饰的只包含数据的类。
    json字符串{"key":123,"title":"This is title"}
    使用kotlin实现:

    data class Bean(
            @SerializedName("key") val key: Int,
            @SerializedName("title") val title: String
    )
    

    使用java显示

    public class Bean{
        @SerializedName("key")
        private int key;
        @SerializedName("title")
        private String title;
    
        public int getKey() {
            return key;
        }
    
        public void setKey(int key) {
            this.key = key;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    }
    

    看上面两段代码,发现kotlin的代码会简洁很多,特别是字段非常多的时候。

    密封类

    密封类用来表示受限的类继承结构:当一个值为有限几种的类型, 而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合 也是受限的,但每个枚举常量只存在一个实例,而密封类 的一个子类可以有可包含状态的多个实例。
    声明一个密封类,使用 sealed 修饰类,密封类可以有子类,但是所有的子类都必须要内嵌在密封类中。 此外,sealed 不能修饰 interface ,abstract class(会报 warning,但是不会出现编译错误)

    sealed class SealedDemo
    data class Const(val number: Double) : SealedDemo()
    data class Sum(val s1: SealedDemo, val s2: SealedDemo) : SealedDemo()
    object NotANumber : SealedDemo()
    fun eval(SealedDemo: SealedDemo): Double = when (SealedDemo) {
        is Const -> SealedDemo.number
        is Sum -> eval(SealedDemo.s1) + eval(SealedDemo.s2)
        NotANumber -> Double.NaN
    }
    

    密封类的关键好处在于使用 when 表达式 的时候,如果能够 验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。

    Kotlin入坑基础篇二

    相关文章

      网友评论

          本文标题:Kotlin入坑基础篇一

          本文链接:https://www.haomeiwen.com/subject/rqzwpftx.html