Kotlin笔记(四)

接口

fun main() {
    val im = IM(2)
    println(im.back())
}

//kotlin接口可以定义属性,不过很少使用
interface IFCallBack {
    val a:Int
    var b:Int
    fun back() : String
}

//实现里面属性和方法都需要加override关键字
//接口是var,实现不能是val,反之是可以的
class IM(override val a: Int) : IFCallBack {

    override var b:Int = 4

    override fun back(): String {
        return (a + b).toString()
    }
}

抽象类

fun main() {
    val main = MainActivity()
    main.initView()
}

class MainActivity : BasActivity(name = "main"){
    override fun onCreate() {
    }
    public override fun initView() {
        super.initView()
    }
}

//抽象类规则与java一致。单继承多实现
abstract class BasActivity (name:String) {
    //抽象方法
    abstract fun onCreate()

    //子类可以覆盖重写的方法需要加open
    protected open fun initView() {
    }
}

泛型类

fun main() {
    val arr = Arr("abc")
    arr.pri(12)
    val arr2 = Arr("dfd")
    arr2.pri(false)
}
//泛型类和java写法一样
class Arr<T : String>(item:T) {
    private var sub = item

    fun <R> pri(r:R) : T {
        println("$sub $r")
        return sub
    }
}

vararg可变长参数

fun main() {
    add(1, 2, 3)
}
//vararg表示可变长参数,相当于java的...
fun add(vararg item:Int) {
    item.forEach {
        println(it)
    }
}

out协变,in逆变

//out协变关键字表示泛型只能作为方法返回值
interface Production<out T> {
    fun product() : T
}
//in逆变关键字表示泛型只能作为方法入参
interface Consumer<in T> {
    fun consumer(item:T)
}
//无关键字泛型既能为方法入参也能为方法返回值
interface ProductionConsumer<T> {
    fun productConsumer(item:T) : T
}

//食物类
open class Food
//快餐食物类
open class FastFood : Food()
//汉堡类
class Burger : FastFood()

//食物商店
class FoodStore : Production<Food> {
    override fun product(): Food {
        println("create Food")
        return Food()
    }
}
//快餐食物商店
class FastFoodStore : Production<FastFood> {
    override fun product(): FastFood {
        println("create FastFood")
        return FastFood()
    }
}
//汉堡商店
class BurgerStore : Production<Burger> {
    override fun product(): Burger {
        println("create Burger")
        return Burger()
    }
}
//食物消费者
class EveryBody : Consumer<Food> {
    override fun consumer(item: Food) {
        println("eat Food")
    }
}
//快餐消费者
class FastPeople : Consumer<FastFood> {
    override fun consumer(item: FastFood) {
        println("eat FastFood")
    }
}
//汉堡消费者
class BurgerPeople : Consumer<Burger> {
    override fun consumer(item: Burger) {
        println("eat Burger")
    }
}

fun main() {
    val food1:Production<Food> = FoodStore()
    food1.product()//create Food
    //使用out关键字的泛型,子类泛型对象可以赋值给父类泛型对象
    val food2:Production<Food> = FastFoodStore()
    food2.product()//create FastFood
    val food3:Production<Food> = BurgerStore()
    food3.product()//create Burger

    //使用in关键字的泛型,父类泛型对象可以赋值给子类泛型对象
    val people1:Consumer<Burger> = EveryBody()
    people1.consumer(Burger())//eat Food
    val people2:Consumer<Burger> = FastPeople()
    people2.consumer(Burger())//eat FastFood
    val people3:Consumer<Burger> = BurgerPeople()
    people3.consumer(Burger())//eat Burger
}

reified关键字

open class Young {
    open val name:String? = null
}
class Boy(override val name: String) : Young()
class Girl(override val name:String) : Young()

//通过reified配合inline内联保存泛型对象类型使用
//内联使用inline关键字使得代码编译时期将执行语句替换到相应位置,少创建对象,优化内存
//下面方法编译后将不存在,语句直接合并至main方法中
inline fun<reified T> getT(item:Young, createT:()->T) : T {
    //传入一个对象,若是T直接返回,否则重新创建一个T对象返回
    return if (item is T) {
        item
    } else{
        createT()
    }
}

fun main() {
    val boy1 = getT(Girl("Girl1")) {
        Boy("Boy1")
    }
    println(boy1.name)
    val boy2 = getT(Boy("Boy2")) {
        Boy("Boy3")
    }
    println(boy2.name)
}

扩展函数

fun main() {
    println("abc".addPlus())
    println("abc".addMoreOne(3))
    12.pri()
    "aaa".pri()
    "sss".anyPri().addPlus().anyPri()
    val strNull:String? = null
    strNull.priNotNull("is Null")
    "The People's Republic of China".numVowels.anyPri()
}
//扩展函数,给任意一个类添加自定义函数,后续该类对象可以直接使用
//扩展函数原理是编译阶段生成一个方法,将前置对象以入参形式传入方法中
//String后面加上plus字符串,单行语句可简写为fun String.addPlus() = this + "plus"
fun String.addPlus() : String {
    return this + "plus"
}
//字符串后面添加num个1
fun String.addMoreOne(num:Int) = this + "1".repeat(num)
//Any父类设置一种打印方法
private fun Any.pri() : Any {
    println(this)
    return this
}
//字符串子类覆盖Any类的方法
private fun String.pri() : String {
    println("字符串$this")
    return this
}
//泛型扩展函数,灵活度更高,apply,let等标准函数的源码都是这个写出来的
private fun <T> T.anyPri() : T {
    println(this)
    return this
}
//可空类型的扩展函数
private fun String?.priNotNull(default:String) = println(this ?: default)
//扩展属性
//定义String的属性表示元音字母的数量
private val String.numVowels
    get() = count {"aeiou".contains(it)}

infix关键字

fun main() {
    val ic = InfixClass()
    ic add 5
    ic pri "abc"
}

//infix关键字使用在有单个参数的类函数与扩展函数中,调用时可省略点和括号
class InfixClass {
    private val num = 20
    infix fun add(other:Int) = println(num + other)
}
infix fun<T> InfixClass.pri(t:T) = println(t)

Kotlin导包别名

package com.kevin.kotlin_test.ext

//定义取集合中的随机元素方法
fun <T> Iterable<T>.randomItem() : T = this.shuffled().first()
package com.kevin.kotlin_test

//导包使用,通过as关键字能取别名使用
import com.kevin.kotlin_test.ext.randomItem as rand

fun main() {
    val list = listOf(1, 2, 3, 4, 5)
    println(list.rand())
}

泛型匿名扩展函数

fun main() {
    val rm = Rm().rm {
        a = "is A"
        b = "is B"
    }
    println(rm.toString())
}
//泛型匿名扩展函数,很多标准函数的原理
//入参是泛型匿名扩展函数的好处是能将对象本身以this隐式传入方法体中(带接收者的函数字面量)
private fun <T> T.rm(block: T.() -> Unit) : T {
    block()
    return this
}
class Rm {
    var a:String? = null
    var b:String? = null
    override fun toString(): String {
        return "a=$a b=$b"
    }
}

DSL-变换函数

//函数式编程范式(DSL):主要依赖于高阶函数(以函数为入参或出参)返回的数据
//Kotlin支持面向对象编程范式和函数式编程范式混用
//函数式编程主要由三类函数构成:变换transform,过滤filter,合并combine。
//每类函数都是针对集合数据类型设计,目标是产生一个最终结果,可以通过链式构建多个简单函数解决复杂的计算
//函数式编程的设计理念是不可变数据的副本在链上函数间传递
fun main() {
    //变换函数会遍历集合内容,用一个以值参形式传入变换器函数,变换每一个元素,然后返回已修改的元素的集合给链上其他函数使用
    //map函数返回的集合中元素个数与原函数必须一样,但元素类型可以不一样
    val list = listOf(1, 2, 3, 4, 5)
    val list2 = list.map {
        it + 2
    }.map {
        it - 3
    }.map {
        "num = $it"
    }
    println(list)
    println(list2)
    println(list2[0]::class.simpleName)
    //flatMap函数将操作多个集合之后进行合并返回合并后的集合
    val flatList = listOf(listOf(1, 2, 3), listOf("4", 5, 6)).flatMap {
        it - 2
    }
    println(flatList)
    flatList.forEach {
        println(it::class.simpleName)
    }
    //对象数据操作,返回元素的引用地址不变
    val dataList = listOf(DslData("DOG"), DslData("Cat"))
    val afterDataList = dataList.map {
        it.name = it.name + "S"
        it
    }
    println(dataList)
    println(afterDataList)
}

class DslData(var name:String)

DSL-过滤函数

fun main() {
    //过滤函数 filter函数遍历集合,把使方法体中返回true的元素加入新集合
    val listFilter = listOf(1, 2, 3, 4, 5, 6).filter {
        it >= 4
    }
    println(listFilter)
}

DSL-合并函数

fun main() {
    val list1 = listOf("A", "B", "C")
    val list2 = listOf(1, 2, 3)
    //合并函数zip能将两个list合并成Pair元素集合,通过toMap方法可转成Map使用
    //合并的两个函数size不同的话生成的集合不会包含超出部分元素
    val zip = list1.zip(list2).toMap()
    println(zip)
    //fold函数表示对一个集合遍历处理,每次循环记录上次的处理结果提供给下一次循环
    //例如下面例子,对1,2,3,4四个数字分别进行平方后相加
    //fold函数入参表示记录的默认值,acc表示上次记录值,i表示当前循环中的元素
    val result = listOf(1, 2, 3, 4).fold(0) { acc, i ->
        acc + i*i
    }
    println(result)
}

DSL的算法示例

fun main() {
    //将二维list集合中带red的元素重新加入到一个新集合中
    val list = listOf(listOf("red apple", "green apple", "blue apple")
            , listOf("red fish", "blue fish")
            , listOf("yellow banana", "green banana"))
    val result = list.flatMap { it -> it.filter { it.contains("red") } }
    println(result)

    //求100以内的质数集合
    //until表示从一个数到最后一个数前一位循环遍历,..是包含最后一位数
    val result100 = (2..100).toList().filter { item ->
        //none表示没有一个符合的返回true
        //每个元素对2到它前一位遍历取模,若取出的结果数组中没有一个为0则代表此数为质数
        (2 until item).map { num -> item % num }.none { it == 0 }
    }
    println(result100)

    //取1到100以内前10个质数,take函数取集合前几位的元素
    println((2..100).toList().filter { it.isZhiShu() }.take(10))
    //generateSequence方法生成Sequence集合
    //在未知集合的size,定义集合的初始元素与下一个元素的生成规则,通过take生成满足条件的Sequence集合
    //不使用take直接使用toList会导致线程挂起
    println(generateSequence(2) { it + 1 }.filter { it.isZhiShu() }.take(10).toList())
}

fun Int.isZhiShu() :Boolean {
    (2 until this).map {
        if (this % it == 0) {
            return false
        }
    }
    return true
}

java与kotlin互相调用

package com.kevin.kotlin_test.ext;

import com.kevin.kotlin_test.JavaData;
import com.kevin.kotlin_test.Kotlin;

import java.io.IOException;

import kotlin.jvm.functions.Function1;

public class Test {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String kotlinClass() {
        System.out.println(Kotlin.javaFun());
        System.out.println(new JavaData().name);
        System.out.println(JavaData.MAX_NUM);
        JavaData.companionFun();
        try {
            Kotlin.javaException();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //java提供0个入参到22个入参的方法类型从Function0到Function22
        Function1<String, String> funData = Kotlin.getFunData();
        System.out.println(funData.invoke("KEVIN"));
        return null;
    }
}
//java调用全局函数变量可以使用的类名重命名
@file:JvmName("Kotlin")
package com.kevin.kotlin_test

import com.kevin.kotlin_test.ext.Test
import java.io.IOException

fun main() {
    val test = Test()
    //java中带有get和set前缀的public方法可直接简化使用
    test.name = "kevin"
    test.age = 22
    println(test.name)
    println(test.age)

    //调用java方法要注意使用空安全符
    test.kotlinClass()?.toString()
}

//java可以使用重载函数调用
@JvmOverloads
fun javaFun(a:String="a", b:String="b") = "aaa"

//java中可以捕获指定异常
@Throws(IOException::class)
fun javaException(){
    throw IOException()
}

class JavaData {
    //java可以直接使用kotlin的set和get方式调用
    @JvmField
    val name:String = "java"

    companion object {
        const val MAX_NUM = 10
        //java中直接通过类名调用伴生对象函数
        @JvmStatic
        fun companionFun() = println("companionFun")
    }
}

//java中调用函数属性
val funData = { it:String ->
    it.toLowerCase().capitalize()
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值