咳特灵才是世界上最好的语言.py(Kotlin学习笔记)

咳特灵

变量与基本类型

变量

  • var 可变
  • val 常量,类似const

声明方式

var 变量名:变量类型
var id:Int
var id:Int = 12  // 直接指明类型
var id = 12  // 自动推断类型

全局变量

直接写在文件中

出厂自带getter、setter

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]

如果不动getter和setter,默认只具备最具出的功能如下

var name: String = "小明"
/*类似这样的函数
fun getName() : String {   //编译时自动生成了对应变量的get函数
    return this.name
}
fun setName(name: String) {  //编译时自动生成了set函数
   this.name = name;
}
*/
fun main() {
    println(name)
    println(getName())   //获取name时本质上是调用getName函数
}

如果想修改这两个函数,可以这么做

var str: String = "尊嘟假嘟"
    set(s) {
        field = s + s    //field表示变量本身的值
    }
    get() = field + "666"

fun main(){
    println(str)
}

流程控制语句

选择结构if-else

大部分用法和其他语言一个鸟样

奇奇怪怪的用法,代替三目运算符

默认将if各分支的最后一行作为返回值

fun main() {
    val score = 2
    //这里判断socre是否大于60,是就得到Yes,否就得到No,并且可以直接赋值给变量
    val res = if (score > 60) "Yes" else "No"
}

直接把返回值丢给res

fun main() {
    val score = 2
    val res = if (score > 60) {
        println("不错啊期末没挂科")
        "Yes"   //代码块默认最后一行作为返回结果
    } else {
        println("不会有人Java期末还要挂科吧")
        "No"
    }
}

选择结构when(疑似代替switch分支)

爪洼和咳特灵对比

switch(目标){
    case 匹配值1:
        代码1...;
        break;
    case 匹配值2:
        代码2...;
        break;
    default:
        代码3...;
}
when (目标) {
    匹配值1 -> 代码1...   //我们需要传入一个目标,比如变量,或是计算表达式等
    匹配值2 -> 代码2...   //如果目标的值等于我们这里给定的匹配值,那么就执行case后面的代码
    else -> {
        代码3...    //如果以上条件都不满足,就进入else中(可以没有),类似于之前的if-elseif-else
    }
}

如果when分支能把所有情况全部包含(编译器也能推断出),那么可以不含else,不然就老老实实写else

同理,在每个分支的最后一行写个值就能当成这个分支的返回值,直接丢给numericValue

fun main() {
    val c = 'A'
    val numericValue = when (c) {
        'B' -> 0
        'A' -> 1
        else -> 2 
    }
}

如果我想像Java一样实现这种情况呢

String agentType=null;
switch(agentId){
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        agentType = "Nao";
    case 6:
    case 7:
    case 8:
        agentType = "Nao2";
    default:
        agentType = "NaoToe";
}

用Kotlin写是这样的

String agentType = when(agentId){
    1,2,3,4,5 -> "Nao"
    6,7,8 -> "Nao2"
    else -> "NaoToe"
}

你可能觉得这样还是太麻烦了,数字得一个个列举,那么好,使用..来连接两个端点表示范围

String agentType = when(agentId){
    in 1..5 -> "Nao"
    in 6..8 -> "Nao2"
    else -> "NaoToe"
}

谁能用Kotlin写个RoboCup3D底层(bushi)

循环结构for

for循环基本结构

for (遍历出来的单个目标变量 in 可遍历目标) 循环体

可遍历目标可以是以下

  • 数组
  • 区间
  • 任何实现了运算符重载函数iterator的类

举栗

$i在字符串中引用循环变量,非常像shell(bushi)

fun main() {
    for (i in 1..3)  //这里直接写入1..3表示1~3这个区间
        println("第$i次循环")
}

指定步长

fun main() {
    for (i in 1..3 step 2)  //这里直接写入1..3表示1~3这个区间
        println("第$i次循环")
}

倒着走(downTo)

fun main() {
    for (i in 10 downTo 1 step 2) {
        println(i)
    }
}

给循环打标签

continue与break同理

fun main() {
    for (i in 1..3) {
        for (j in 1..3) {
            if (i == j) break  //break只会终结内部循环
            println("$i, $j")
        }
    }
}

打标签就可以实现在内部循环对外部循环进行控制

fun main() {
    outer@ for (i in 1..3) {   //在循环语句前,添加 标签@ 来进行标记
        inner@ for (j in 1..3) {
            if (i == j) break@outer  //break后紧跟要结束的循环标记,当i == j时终止外层循环
            println("$i, $j")
        }
    }
}

循环结构while

while循环基本结构

while(循环条件) 循环体
do{
    循环体
}while(循环条件)

其他用法基本没什么差别,也可以打标签

函数

函数基本格式

fun 函数名(参数1:类型,参数2:类型...):返回值类型{

}

函数参数以及类型标注

fun sum(a: Int, b: Int) : Int {
    return a + b  //使用return语句将结果返回
}

如果没有返回值也可以不写返回值类型

fun main() {
    test("香翅捞饭")
}
fun test(str:String) {
    println(str)
}

参数缺省值可以像C++,py那样

fun main() {
    test()   //调用函数时,如果对应参数有默认值,可以不填
}
fun test(text: String = "我是默认值"){
    println(text)
}

若有多个可以缺省的,且不都在参数列表最后,可以像py那样直接用键值对指定要填写哪个参数

fun main() {
    test(b = 3)  //这里如果只想填写第二个参数b,我们可以直接指定吧实参给到哪一个形参
    test(3)   //这种情况就是只填入第一个实参
}
fun test(a: Int = 6, b: Int = 10): Int {
    return a + b
}

超级简化

fun test(a: Int = 6, b: Int = 10): Int = a + b   //函数的结果直接缩减为 = a + b 效果跟之前是一样的
fun test(a: Int = 6, b: Int = 10) = a + b  //返回类型可以自动推断,这里可以吧返回类型省掉

函数嵌套

fun outer(){
    fun inner(){
    }
    inner()
}

函数重载

fun test() = println("A")
fun test(str: String) = println("B")  //参数列表不一致

递归尾优化

tailrec fun test(n: Int, sum: Int = 0): Int {
    if(n <= 0) return sum   //到底时返回累加的结果
    return test(n - 1, sum + n)  //不断累加
}

编译之后的样子

例:斐波那契

tailrec fun fib(n: Int, prev: Int = 0, next: Int = 1): Int {
    return if (n == 0) prev else fib(n - 1, next, prev + next)  //从0和1开始不断向后,直到n为0就返回
}

常用函数

fun main(){
    print()
    println()
    val text = readln()

    1.6.pow(4.0)  //我们可以使用pow方法直接计算a的b次方
    abs(-1);    //abs方法可以求绝对值
    max(19, 20);    //快速取两个数的最大值
    min(2, 4);   //快速取最小值
    sqrt(9.0);    //求一个数的算术平方根

    //这里我们可以直接使用库中预设好的PI
    sin(PI / 2);     //求π/2的正弦值,这里我们可以使用预置的PI进行计算
    cos(PI);       //求π的余弦值
    tan(PI / 4);    //求π/4的正切值
    asin(1.0);     //三角函数的反函数也是有的,这里是求arcsin1的值
    acos(1.0);
    atan(0.0);

    ln(E)    //e为底的对数函数,其实就是ln,我们可以直接使用Math中定义好的e
    log10(100.0)    //10为底的对数函数
    log2(8.0)    //2为底的对数函数
    //利用换底公式,我们可以弄出来任何我们想求的对数函数
    val a = ln(4.0) / ln(2.0) //这里是求以2为底4的对数,log(2)4 = ln4 / ln2
    println(a)

    ceil(4.5) //通过使用ceil来向上取整
    floor(5.6) //通过使用floor来向下取整
}

高阶函数与lambda表达式

将函数看成了变量

var func0: (Int) -> Unit  //这里的 (Int) -> Unit 表示这个变量存储的是一个有一个int参数并且没有返回值的函数
var func1: (Double, Double) -> String   //同理,代表两个Double参数返回String类型的函数

现在可以把函数当成变量用了(作为函数参数传递)

fun test(other: (Int) -> String){
    println(other(1))  //这里提供的函数接受一个Int参数返回string,那么我们可以像普通函数一样传入参数调用它
}

给lambda函数起个别名

typealias HelloWorld = (String) -> Double  // 使用类型别名关键字定义HelloWorld

fun main() {
    var func: HelloWorld  // 创建一个HelloWorld类型的变量
}

函数的具体表示

可以先定义一个正常的函数,然后让一个变量等于他,两个函数类型要一致

fun main() {
    var func: (String) -> Int = ::test   //使用双冒号来引用一个现成的函数
}

fun test(str: String): Int {
    return 666
}

可以直接用匿名函数(很像js啊),那么匿名函数就有了名字func

fun main() {
    val func: (String) -> Int = fun(str: String): Int {
        println("这是传入的内容$str")
        return 666
    }
}

用lambda定义函数

一个Lambda表达式只需要直接在花括号中编写函数体即可

默认情况下,如果函数只有一个参数,我们可以使用it代表传入的参数

函数体最后一行的值作为返回值

fun main() {
    var func: (String) -> Int = {
        println("这是传入的参数$it")
        666
    }
    func("HelloWorld!")
}

如果函数有好几个参数呢?

fun main() {
    val func: (String, String) -> Unit = { a, b ->   // 手动添加两个参数这里的形参名称
        println("这是传入的参数$a, 第二个参数$b")   // 直接使用上面的形参
    }
    val func2: (String, String) -> Unit = { _, b ->
        println("这是传入的第二个参数$b")   // 假如这里不使用第一个参数,也可以使用_下划线来表示不使用
    }
    func("Hello", "World")
}

如果函数的最后一个参数是函数类型的,那么调用时,其他非参数类写在括号里,最后一个参数可以直接lambda,比如

fun main() {
    test("小明") {
        println("用中文说$it")
    }
}

fun test(name:String,speak:(String)->Unit){
    print(name)
    speak("我是sb")
}

关于lambda中的return

在Lambda中没有办法直接使用return语句返回结果,而是需要用到之前的标签

fun main() {
    val func: (Int) -> String = test@{
        //比如这里判断到it大于10就提前返回结果
        if(it > 10) return@test "我是提前返回的结果"
        println("我是正常情况")
        "收到的参数为$it"
    }
    test(func)
}

fun test(func: (Int) -> String) {
    println(func(66))
}

如果是函数调用的尾随lambda表达式,默认的标签名字就是函数的名字

fun main() {
    testName {  //默认使用函数名称
        if(it > 10) return@testName "我是提前返回的结果"
        println("我是正常情况")
        "收到的参数为$it"
    }
}
fun testName(func: (Int) -> String) {
    println(func(66))
}

内联函数

和之前的C++内联函数差不多

内联函数的return

直接返回main

fun main() {
    test { return@main }  //标签可以直接指定为外层函数名称main来提前终止整个外部函数
    println("调用上面方法之后")
}

inline fun test(func: (String) -> Unit){
    func("HelloWorld")
    println("调用内联函数之后")
}

返回调用它的test函数

fun main() {
    test { return@test }  //这样就只会使test返回,而不会影响到外部函数了
    println("调用上面方法之后")
}

inline fun test(func: (String) -> Unit){
    func("HelloWorld")
    println("调用内联函数之后")
}

多个高阶函数的情况

有些时候,可能一个内联的高阶函数中存在好几个函数参数,但是我们希望其中的某一个函数参数不使用内联,能够跟之前一样随意当做变量使用

fun main() {
    test({ println("我是一号:$it") }, { println("我是二号:$it") })
}

//在不需要内联的函数形参上添加noinline关键字,来防止此函数的调用内联
inline fun test(func: (String) -> Unit, noinline func2: (Int) -> Unit){
    println("这是一个内联函数")
    func("HelloWorld")
    var a = func2  //这样就不会报错,但是不会内联了
    func2(666)
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇