Kotlin 之类和接口

简介: Kotlin 之类和接口


默认为 pulic


class Two {
    var x:Int = 0;//必须初始化
    //构造方法
    constructor(x:Int){
        this.x = x
    }
    //定义方法
    fun y(){
    }
}


简写


class Two(var x: Int) {
    var y: Int = x
}
class A(var y: Int) {
}
class B(var x: Int, var y: String) {
}
fun main() {
    val two = Two(1)
    println(two.y + two.x)
    val a = A(3)
    println(a.y)
    val b = B(3, "hello")
    println(b.y + "  " + b.x)
}


接口


interface SimpleInf {
    val x: Int
    var y: Int
    fun simpleMethod()
}
class Two() : SimpleInf {
    //实现 接口中的参数,因为是可读,所以必须 + get 方法
    override val x: Int = 0
        get() {
            return field
        }
    override var y: Int = 10
        get() {
            return field
        }
        set(value) {
            field = value
        }
    //必须写 override
    override fun simpleMethod() {
        println(x)
        println(y)
    }
}
//在构造方法中直接初始化 接口中的变量
class A(override val x: Int, override var y: Int) : SimpleInf {
    override fun simpleMethod() {
        println(x)
        println(y)
    }
}
fun main() {
    val t = Two()
    t.simpleMethod() // 0 ,10
    //获取属性引用
    val g = t::y
    g.set(5)
    println(t.simpleMethod()) //0 ,5
    val a = A(3, 3)
    a.simpleMethod() //3 ,3
}


抽象类


abstract class Two {
    abstract fun abs()
    //方法默认不可复写需要复写则需要加 open 关键字
    open fun over() {
    }
    //不可复写
    fun non() {
    }
}
class A : Two() {
    override fun abs() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
    override fun over() {
        super.over()
    }
    //non 方法不能重写
}


类继承


open class Two {
    open fun a() {}
    open fun b() {}
    fun c() {}
}
//继承的类必须加 Open
open class A : Two() {
    //重写的方法必须是 open
    override fun a() {
        super.a()
    }
    //将重写类方法变为不可重写
    final override fun b() {
        super.b()
    }
}
class B : A() {
    override fun a() {
        super.a()
    }
}


属性


Kt 中不需要我们定义 get / 和 set 方法,就算是定义了,使用的时候也是通过 类.属性的方式来读写,而不是 get / set,如下


class Persion {
    var name: String = ""
        get() {
            return field //field 表示 属性:name
        }
        set(value) {
            field = value //设置 value
        }
    // get 和 set 推荐不用写
    var age: Int = 0
}
fun main() {
    val p = Persion()
    println(p.name)
    println(p.age)
}


扩展方法/属性


fun main() {
    val s = String::setEmail
    val s1: (String, String) -> String = String::setEmail
    val fiel = PoorGuy::moneyLeft
    var fiel1: KMutableProperty1<PoorGuy, Double> = PoorGuy::pocket
}
class PoorGuy {
    var pocket: Double = 0.0
}
//扩展方法
fun PoorGuy.noMoney() {
}
//扩展属性
var PoorGuy.moneyLeft: Double
    get() {
        return pocket;
    }
    set(value) {
        pocket = value
    }
//扩展 String 类方法
fun String.setEmail(s: String): String {
    return "${s}@163.com"
}


某个类的扩展方法如果定义在别的类中:


class D2 {
    fun Class<D1>.set() {
    }
}


如何调用呢,如下:


class D2 {
    fun Class<D1>.set() {
    }
    //在内部调用
    fun X() {
        D1().javaClass.set()
    }
}
fun main() {
  //其实 run 也是一个扩展方法
    D2().run {
        D1().javaClass.set()
    }
}


空类型安全的概念


var nonNull:String = "hello"
//    nonNull = null
//不可空类型


任何 类型在类型后面+?即为可 null


var nonNull: String? = "hello"
 val length = nonNull!!.length   //强转为 Null
 val l = nonNull?.length //nonNull 如果为 null,则 l 也为 null,否则返回对应的长度


那 如果 l 也 为 null 呢?可以采用如下方式:


val x: Int = nonNull?.length ?: 0 //elvis 表达式,表达式为 null 返回 0


空类型继承关系


fun main() {
    var x: String = "Hello"
    var y: String? = "World"
    x = y   //类型不匹配
    y = x   //Ok ,根据李氏替换原则就可知道 String 应该是 String?的子类
    //里氏替换原则说:任何基类可以出现的的地方,子类一定可以出现
    // 也就是子类在一切场景下都可以替换他的父类
    //例如  Int 是 Number 的子类
    var a: Int = 2;
    var b: Number = 2;
    a = b;  //类型不匹配
    b = a;
    //从上面就可以看出 String 应该是 String?子类
}


平台类型


0a2653c851af460fa595bd959398a8f1.png


Kt 代码可以编译为字节码类型,还有 JavaScript ,Natvie。。


智能类型转换


fun main() {
    val k: KotLiner = Person()
    // is 等价于 instanceof,判断一个类型是否为一个类型
    if (k is Person) {
        //智能转换为 Person 
        println(k.name)
    }
}


类型的安全转换


println((k as? Person)?.name)


转换 成功,就会得到 Person 类型,否则就是 null


例子


使用 Retrofit 发送一个网络请求

首先,加一下依赖


implementation 'com.squareup.retrofit2:retrofit:2.6.2'
 implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
 implementation 'com.google.code.gson:gson:2.8.1'


接着发送请求:


interface Api {
    //    Retrofit
    @GET("/repos/{owner}/{repo}")
    fun getRepository(@Path("owner") owner: String, @Path("repo") repo: String): Call<Repository>
}
fun main() {
    val api = Retrofit.Builder().baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(Api::class.java)
    val response = api.getRepository("Jetbrains", "kotlin").execute()
    val repository = response.body()
    if (repository == null) {
        println("Error!{${response.code()} - ${response.message()}")
    } else {
        println(repository.name)
        println(repository.owner.login)
        println(repository.stargazers_count)
        println(repository.forks_count)
  //生成一个文件
        File("Kotlin.html").writeText(
            """
            <!DOCTYPE html>
            <html>
                <head>
                    <meta charset="UTF-8">
                    <title>${repository.owner.login} - ${repository.owner.login} - ${repository.name}</title>
                </head>
                <body>
                    <h1> <a href = '${repository.html_url}'>${repository.owner.login}-${repository.name}</a></h1>
                    <p>${repository.description}</p>
                    <p>Start:${repository.stargazers_count}</p>
                    <p>Forks:${repository.forks_count}</p>
                </body>
            </html>
        """.trimIndent()
        )
    }
}


//结果
kotlin
JetBrains
30195
3602


总结


类和接口


类:实例化不用写 new ,方法,类被继承或者重写必须加上 open 关键字,构造器可以写在类后面


接口


抽象类:基本和上面的差不多,override 作为关键字使用,而不是注解


属性:field+getter+setter,不需要手动的 get / set。属性引用


扩展方法


定义方法

方法/函数引用,在方法签名+类,函数引用,直接 :: 函数

空类型安全


可空类型为不可空类型的父类。Kt 中声明类型的时候就可以明确的告诉编译器类型是否可以为 null,如果不可为 null,编译器就会有权利要求你不能给他赋值为 null

运算符

!! :强制转换为不可空 类型

?. :安全调用成员,如果不确定是否为空,可以使用这种方式,如果为 null,整个表达式返回 null,

?: :上述如果表达式返回 null 可以使用 ?: 返回一个默认值

平台类型

Java 虚拟机上就是 java 原生类型

javaScript 上就是 javaScript 的类型

Native 则是 C 对应的类型

智能类型替换


A as B 类型转换


A as? B 安全类型转换,失败返回 null


只能类型转换的适用场景


Retrofit 发送网络请求


使用 Java 的第三方框架

使用 KotLin 的文件扩展写文件

使用 Raw 字符串


建议


尽可能使用 val 声明不可变引用,让程序的含义更加清晰确定

尽可能减少对外部变量的访问,也为函数式编程提供基础

必要时创建局部的变量指向外部,避免因它的变化引起程序错误

这种方式,如果为 null,整个表达式返回 null,

- ?: :上述如果表达式返回 null 可以使用 ?: 返回一个默认值


平台类型


Java 虚拟机上就是 java 原生类型

javaScript 上就是 javaScript 的类型

Native 则是 C 对应的类型

智能类型替换


A as B 类型转换


A as? B 安全类型转换,失败返回 null


只能类型转换的适用场景


Retrofit 发送网络请求


使用 Java 的第三方框架

使用 KotLin 的文件扩展写文件

使用 Raw 字符串


相关文章
|
2月前
|
数据安全/隐私保护 Kotlin
Kotlin - 类成员
Kotlin - 类成员
64 6
|
2月前
|
Java 物联网 Kotlin
Kotlin - 面向对象之抽象类与接口
Kotlin - 面向对象之抽象类与接口
|
1月前
|
Kotlin
Kotlin教程笔记(20) - 枚举与密封类
Kotlin教程笔记(20) - 枚举与密封类
46 8
|
2月前
|
Kotlin
Kotlin - 枚举与密封类
Kotlin - 枚举与密封类
29 3
Kotlin - 枚举与密封类
|
1月前
|
Java Kotlin
Kotlin教程笔记(13) - 类及成员的可见性
Kotlin教程笔记(13) - 类及成员的可见性
44 3
|
1月前
|
Java 物联网 Kotlin
Kotlin教程笔记(11) - 面向对象之抽象类与接口
Kotlin教程笔记(11) - 面向对象之抽象类与接口
31 2
|
1月前
|
存储 前端开发 Java
Kotlin教程笔记(18) - 数据类
Kotlin教程笔记(18) - 数据类
|
2月前
|
数据安全/隐私保护 Kotlin
Kotlin教程笔记(7) - 类成员
Kotlin教程笔记(7) - 类成员
33 5
|
2月前
|
数据安全/隐私保护 Kotlin
Kotlin - 类成员
Kotlin - 类成员
54 9
|
2月前
|
Java 开发者 Kotlin
Kotlin教程笔记(2) - 类与构造器
Kotlin教程笔记(2) - 类与构造器
31 1

热门文章

最新文章