Kotlin/Dart的高阶函数有哪些差异
前语
函数式编程咱们都不陌生了,可是为什么 Dart 的函数与 Kotlin 的函数体现与写法有这么大的差异?
其实叫法咱们都是函数,高阶语言的特性能够把函数作为参数,变量,返回值等,也称之为高阶函数,在 Dart 与 Kotlin 中其实他们的运用思路是共同的。仅仅写法不同。
既然如此,那么高阶函数的扩展 DSL 等特性,如果 Kotlin 能够完成,在 Dart 中能不能完成呢?
话不多说,直接开端吧!
一、Kotlin 的高阶函数
Kotlin的函数是比较简单的:
//Kotlin 中函数类型的语法规矩
(String,Int) -> Unit
//或许如下有返回值
() -> Int
参数和返回值,一看就懂。
咱们用一个类中的办法,界说两个高阶函数用于回调处理的数据:
class NetTest : CoroutineScope by MainScope() {
fun start(onSuccess: (srcPath: String, resultPath: String) -> Unit, onError: (error: String) -> Unit) {
launch {
val result = withContext(Dispatchers.IO) {
delay(500)
return@withContext Random().nextInt(10)
}
when {
result > 5 -> {
onSuccess.invoke("123", "456")
}
else -> {
onError.invoke("过错的音讯")
}
}
}
}
这个咱们都懂,那么其实咱们继续用 DSL 的办法回调。
class NetTest : CoroutineScope by MainScope() {
fun start(onSuccess: (srcPath: String, resultPath: String) -> Unit, onError: (error: String) -> Unit) {
launch {
mCallback?.start()
val result = withContext(Dispatchers.IO) {
delay(500)
return@withContext Random().nextInt(10)
}
when {
result > 5 -> {
onSuccess.invoke("123", "456")
mCallback?.onSuccess("123", "456")
}
else -> {
onError.invoke("过错的音讯")
mCallback?.onError("过错的音讯")
}
}
}
}
var mCallback: CompressImpl? = null
fun setCompress(callback: CompressImpl) {
this.mCallback = callback
}
}
界说对应的接口回调:
interface ICompress {
fun onSuccess(srcPath: String, resultPath: String)
fun onError(error: String)
fun start()
}
界说自界说的接口回调与桥接类
class CompressImpl : ICompress {
private var onSuccess: ((String, String) -> Unit)? = null
private var onError: ((String) -> Unit)? = null
private var start: (() -> Unit)? = null
fun onSuccess(method: (String, String) -> Unit) {
onSuccess = method
}
fun onError(method: (String) -> Unit) {
onError = method
}
fun start(method: () -> Unit) {
start = method
}
override fun onSuccess(srcPath: String, resultPath: String) {
onSuccess?.invoke(srcPath, resultPath)
}
override fun onError(error: String) {
onError?.invoke(error)
}
override fun start() {
start?.invoke()
}
}
界说扩展办法,DSL的进口:
fun NetTest.setCompressDsl(init: CompressImpl.() -> Unit) {
val listener = CompressImpl()
init(listener)
this.setCompress(listener)
}
运用的:
fun dsl() {
val netTest = NetTest()
netTest.start(onSuccess = { x, y ->
YYLogUtils.w("x:$x y:$y")
}, onError = {
YYLogUtils.w("it:$it")
})
netTest.setCompressDsl {
start {
YYLogUtils.w("开端")
}
onSuccess { x, y ->
YYLogUtils.w("x:$x y:$y")
}
onError {
YYLogUtils.w("it:$it")
}
}
}
结果:
先调用的扩展办法的回调,后面打印的时候DSL的回调办法。
二、Dart 的高阶函数
Dart的函数概念与 Kotlin 相似,仅仅界说的办法不同
//Dart 中的函数类型的语法规矩
void Function(String,int)
//或许如下带返回值
Strign Function()
那么咱们用相同的办法界说代码为:
class NetTest {
void start({required Function(String srcPath, String resultPath) onSuccess, required Function(String error) onError}) {
Future.delayed(Duration(milliseconds: 500), () {
int result = Random().nextInt(10);
if (result > 5) {
onSuccess("123", "456");
} else {
onError("过错的音讯");
}
});
}
void setCompress(CompressImpl callback) {
mCallback = callback;
}
}
咱们相同的用高阶函数界说了回调的结果。
如果咱们想在 Dart 中运用 DSL 的办法回调接口的处理也是相同的作用:
abstract class ICompress {
void onSuccess(String srcPath, String resultPath);
void onError(String error);
void start();
}
class CompressImpl implements ICompress {
Function(String, String)? _onSuccess;
Function(String)? _onError;
Function()? _start;
void OnSuccess(Function(String, String) method) {
_onSuccess = method;
}
void OnError(Function(String) method) {
_onError = method;
}
void OnStart(Function() method) {
_start = method;
}
@override
void onSuccess(String srcPath, String resultPath) {
_onSuccess?.call(srcPath, resultPath);
}
@override
void onError(String error) {
_onError?.call(error);
}
@override
void start() {
_start?.call();
}
}
class NetTest {
CompressImpl? mCallback;
void start({required Function(String srcPath, String resultPath) onSuccess, required Function(String error) onError}) {
mCallback?.start();
Future.delayed(Duration(milliseconds: 500), () {
int result = Random().nextInt(10);
if (result > 5) {
onSuccess("123", "456");
mCallback?.onSuccess("123", "456");
} else {
onError("过错的音讯");
mCallback?.onError("过错的音讯");
}
});
}
void setCompress(CompressImpl callback) {
mCallback = callback;
}
}
extension CompressDsl on NetTest {
void setCompressDsl(void Function(CompressImpl) init) {
CompressImpl listener = CompressImpl();
init.call(listener);
setCompress(listener);
}
}
运用:
var test = NetTest();
test.start(onSuccess: (x, y) {}, onError: (e) {});
test.setCompressDsl((c) {
c.OnStart(() => {
Log.d("开端")
});
c.OnSuccess((x, y) => {
Log.d("x:$x y:$y")
});
c.OnError((e) => {
Log.d("e:$e")
});
});
作用:
跋文
其实他们的差异就是 it 和 this 的差异:
//这里的`init(listener)`实际上是调用`CompressImpl`上的扩展函数,其中`listener`作为`this`隐式接收者。这允许在`init`块内部直接访问`CompressImpl`的特点和函数,而无需运用任何前缀。
fun NetTest.setCompressDsl(init: CompressImpl.() -> Unit) {
val listener = CompressImpl()
init(listener) // 在这里,listener 是 implicit receiver
this.setCompress(listener)
}
//在 Dart 中,没有直接等价于 Kotlin 中的 "implicit receiver" 特性。Dart 的函数传递和 lambda 表达式更直接、传统,没有这种基于扩展函数的隐式接收者概念。在 Dart 中,要操作特定目标的特点或办法,你需求明确引用该目标。
fun NetTest.setCompressDsl(init: (CompressImpl) -> Unit) {
val listener = CompressImpl()
init(listener)
this.setCompress(listener)
}
Kotlin 能够用它的 implicit receiver 特性,把 it 变成 this,到达双 this 的作用,这里很多人也称之为高阶扩展函数,而 Dart 就必须要用 it 去手动的点出来赋值函数的办法,显得不是那么优雅。
其次他们还有很多小技巧相同的地方,比方都能够设置别名,通过 typedef 能够给函数起别名,这一点在 Flutter 中运用特别广泛。
例如:
typedef ComprerssSuccess = void Function(String srcPath, String resultPath);
class NetTest {
void start({required ComprerssSuccess onSuccess, required Function(String error) onError}) {}
}
其实在 Kotlin 中也能够这么用,仅仅咱们用的少而已
typealias IntOperation = (Int, Int) -> Int
fun performOperation(x: Int, y: Int, operation: IntOperation): Int { return operation(x, y) } val sum: IntOperation = { a, b -> a + b }
val resultSum = performOperation(2, 3, sum)
要不怎么说这个系列叫参考之资呢?我之前也是不了解 Kotlin 还有这功能呢,自己也是跟着学习了一波。
言归正传,理解和掌握函数式思维,不管是 Dart 语法仍是 Kotlin 语法,不管是写代码仍是阅读源码都会更流畅。
那么本期内容就到这里了,如讲的不到位或讹夺的地方,期望同学们能够评论区指出。
由于代码比较简单,本文悉数贴出,如果感觉本文对你有一点点点的启示,还望你能点赞
支持一下,你的支持是我最大的动力啦。
Ok,这一期就此结束。