Skip to content

Commit

Permalink
Kotlin基础语法之函数相关
Browse files Browse the repository at this point in the history
  • Loading branch information
iOrchid committed Mar 16, 2024
1 parent 77c9059 commit 24627dd
Show file tree
Hide file tree
Showing 4 changed files with 325 additions and 0 deletions.
147 changes: 147 additions & 0 deletions kotlin/src/main/kotlin/org/zhiwei/kotlin/concepts/SyntaxFunction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package org.zhiwei.kotlin.concepts

/**
* kotlin语法基础之 函数相关
*/
class SyntaxFunction {

//region 0.扩展函数
open class Super
class Sub : Super()

//扩展函数,定义访问作用域,扩展者的,以及函数具体实现
private fun Sub.school() {
println("扩展Sub一个函数叫school")
}

private fun Super.school() {
println("扩展Super函数,叫school")
}

//扩展函数,可理解为静态工具类,并不会修改被扩展类;所以
fun testExt() {
Sub().school()//此时就可以使用扩展函数了。调用sub的扩展
val str: Super = Sub()
str.school()//调用super的扩展,虽然str是sub的对象,但是声明的是Super类,所以叫静态扩展。
}
//todo 如果扩展函数与内部已经有的函数完全一致,则调用自有的。扩展失效。

//1. 扩展属性,类似于扩展函数,但是扩展属性是没有初始化的,可以手动setter,getter
private var Super.sss
get() = "Sp额sss"
set(value) {
//因为是扩展属性,对于Super类就没有这个字段,所以setter只能用来做别的事
println("可以给其他值运算等 $value")
}
//也可以给类的伴生对象companion object扩展;
// 可以在需要的地方扩展定义,其作用域根据需要选择修饰符;
//endregion 也可以在open类内定义open的扩展函数,给子类也能实现override,不过如此做法,场景业务不多


//region 1.函数定义,lambda,内联函数,操作符重载
fun empty(): Unit {
println("无参无返回值的普通函数")
}

fun params(a: Int, b: String, c: Char = 'A'): Boolean {
println("这是一个有参数,且有默认参数$c 设置的函数定义,返回值布尔类型,")
return a > b.length
}

open class SuperFun {
open fun foo(a: Int = 3) {}
}

class SubFun : SuperFun() {
//如果基类函数的参数有默认值,则实现类override时候,不能写默认值
override fun foo(a: Int) {
super.foo(a)
}
}

private fun paramsFun(funParam: (num: Int, str: String) -> Boolean) {
println("这里形参是一个匿名函数表达式,指明了参数的名字,也可以简写(Int,String)->Boolean")
}

//多个参数 vararg必须是放在函数定义的最后一个参数位置
private fun manyParams(a: Int, vararg bb: String) {}

infix fun String.sdcard(a: Int) {
println("中缀函数的定义,必须是扩展函数;有且仅有一个参数;不能是vararg的,也不能有默认值")
}


//尾递归函数,替代一些循环,解决堆栈溢出的风险
val eps = 1E-10 // "good enough", could be 10^-15
tailrec fun findFixPoint(x: Double = 1.0) {
if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))
}

private fun testFun() {
//调用函数,
empty()
params(3, "ss")//因为c参数有默认值,可以不传
params(b = "dd", a = 99, c = 'D')//可以根据形参名称,传入,而不用顾及顺序
//调用表达式的函数,如果最后一个参数是表达式,可以括号内,也可以括号外,
paramsFun({ num, str -> str.length > num })
paramsFun { num, str -> str.length > num }
manyParams(3, "ad", "dsd")
//中缀函数使用
"abd".sdcard(66)
"abd" sdcard 66
findFixPoint(3.0)
}

//lambda函数表达式 ,表达式用做函数的参数,比定义接口更方便;
val lab = { a: Int -> a > 90 }

//函数定义为变量表达,匿名函数
val ss = fun(s: String): Int { return s.length }

//多重表达式,返回类型还是表达式形式的
val lablab = { b: String -> { c: Int -> c > 100 } }

//lambda表达式中,单个参数可以不写参数名,默认是it,不用的话,使用_下划线处理
// 系统提供了apply,also,run,with,let等扩展函数,作用区别就是返回值和语义不同


private fun testLambda() {
//调用lambda可以invoke,也可以直接()入参
lab.invoke(3)
ss("北包包")
lablab.invoke("哈哈哈")
//系统提供的函数,可以使用::调用,invoke
List<String>::size.invoke(listOf("abd", "cdsd"))

}


//endregion

//高阶函数lambda 每个函数都是一个对象,所以无形中也会增加性能消耗,必要时候减少函数创建,使用inline内联
fun abd(): () -> Unit {
return { println("kongkong") }
}

//inline用于函数内联,调用者其实就是贴进来一段代码,而不是函数;
//noinline,只能修饰inline函数的参数,让这个参数不参与内联;
//corssinline,因为break continue在inline函数中不可用,涉及到return返回的问题,该修饰符使得inline函数的参数不能使用内部的return
inline fun ddd(noinline ab: () -> Unit, crossinline ee: () -> Double, c: String) {

}

private fun ddff() {
ddd(abd(), { 2.0 }, "")
}


//还可以有内联属性,内联属性不能有setter的field
inline var ssssss: String
get() {
return "TODO()"
}
set(value) {
println("咋办,啥用")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.zhiwei.kotlin.concepts

/**
* kotlin语法基础之 接口
*/
class SyntaxInterface {

//0. 接口的定义使用interface关键字,没有构造函数, 可以有函数声明,且函数可以有默认的实现
interface Shape {

val ss: String //接口的属性,是抽象的,不能初始化赋值,实现类会赋值
val ddd: String //要么是提供一个getter访问
get() = "ddd"
var ee: String
set(value) {
// field=value+""//在接口的属性上,就不同用field设置setter了
}
get() = "eee"

fun draw()//接口的函数

fun foo() {
//可以有默认实现的
}
}

//1. 接口可以继承其他接口,也可以给基类接口的抽象函数一个默认实现,那么后续的子类实现该接口的话,可选择不必实现已经有默认实现的函数
interface SuperInterface {
fun foo()
}

interface CommonInterface : SuperInterface {
fun boo()
fun zoo()

override fun foo() {
println("默认实现了foo,")
}
}

class SubClass : CommonInterface {
override fun boo() {

}

override fun zoo() {

}
//对于foo函数,就可以选择实现或不实现

}

//2. 多接口实现的时候,可能会出现函数名冲突,需要实现类显式的指明,参见[SyntaxInheritance]中line 62行,类似。

//3. SAM单一抽象接口,只有一个函数定义的接口,在kotlin中就可以简化为lambda方式
private fun testSam() {
//kotlin中函数内可以定义局部函数
fun aSam(su: SuperInterface) {
su.foo()
}
//非Sam形式
aSam(object : SuperInterface {
override fun foo() {

}
})
val fo = object : SuperInterface {
override fun foo() {

}
}
fo.foo()
}

//可以定义简短的SAM接口,只能是SAM式的才可以如此
fun interface SamInterface {
fun abc(name: String)
}

private val sam = SamInterface { name ->
println(name)
}

fun testSam2() {
fun hhh(ine: SamInterface) {

}
sam.abc("Kotlin测试Sam")
hhh(sam)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.zhiwei.kotlin.concepts

/**
* Kotlin语法基础之 权限修饰符
*/

//0. kotlin中权限修饰符有private internal protected 和public;一般如果是public则默认不写

//1. 在package内,也就是kt文件topLevel可声明 属性,函数,类,接口,对象等。
/*
1.1 private 权限表示在作用域内私有,外部不可访问。
internal 权限表示同一包package内可访问。
protected 权限表示子类实现类可访问。(不可用于topLevel的声明处)
public 权限公开。
*/

class SyntaxModifier protected constructor() {
private val sName = ""

/*
1.2 在类内部,权限修饰符的作用:
private 这个类内部(包含其所有成员或内部类里面)可见;
protected 与 private 差不多,但也在子类中可见。
internal 本模块内可见
public 能见到类声明的都可见其 public 成员。
*/
//这叫嵌套类,不同于Java,
class NestClass {
private val nName = ""
fun test() {
// sName //嵌套类不能访问到外部类的私有属性,就立即为两个独立的类,只是文件上有了交集而已。
}
}

//这才叫内部类
inner class InnerClass {
private val inName = ""
fun test() {
sName //可以访问到外部类的私有属性,内部类会有外部类的引用的,所以可以。不同于嵌套类。
}
}

fun testNestInner() {
// NestClass().nName//无法访问到嵌套类的私有属性
// InnerClass().inName//无法访问到内部类的私有属性
}

//继承时候,复写基类的函数,权限可以放大,不能缩小;返回值类型,则是可以缩小而不能放大

open class Super {
protected open fun aa() {}

protected open fun bb(): Any {
return 3
}
}

class Sub : Super() {
public override fun aa() {
super.aa()
}

override fun bb(): Int {
return 2
}
}

//权限修饰符可以作用于 构造函数上
//局部变量、函数和类不能有可见性修饰符。
//internal 作用域可理解为IDE的一个module内
}
16 changes: 16 additions & 0 deletions kotlin/src/test/java/org/zhiwei/kotlin/ExampleUnitTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.zhiwei.kotlin.basic.testCollection
import org.zhiwei.kotlin.basic.testParseIntNull
import org.zhiwei.kotlin.basic.testWhen
import org.zhiwei.kotlin.concepts.SyntaxClassObject
import org.zhiwei.kotlin.concepts.SyntaxFunction

/**
* Example local unit test, which will execute on the development machine (host).
Expand Down Expand Up @@ -105,4 +106,19 @@ class ExampleUnitTest {
println("初始化子类是小写字母的hello world")
Derived("hello", "world")
}

private fun SyntaxFunction.Sub.school() {
println("扩展Sub一个函数叫school")
}

private fun SyntaxFunction.Super.school() {
println("扩展Super函数,叫school")
}

@Test
fun testExt() {
SyntaxFunction.Sub().school()//此时就可以使用扩展函数了。
val str: SyntaxFunction.Super = SyntaxFunction.Sub()
str.school()
}
}

0 comments on commit 24627dd

Please sign in to comment.