首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

  • 24-11-26 09:06
  • 3034
  • 140904
juejin.cn

视频先行

这是一篇视频形式的分享,如果你方便看,可以直接去看视频:

  • 哔哩哔哩:这里
  • 抖音:这里
  • YouTube:这里

下面是视频内容的脚本文案原稿分享。

小剧场

面试官:「既然协程和泛型你都熟悉,flow() 函数是怎么实现类型推断的有了解过吗?」

求职者:「嗯……」

求职者:「嗯……在Kotlin协程中,flow 是一种构建器,用于创建 Flow 类型的实例。Flow 是 Kotlin 中处理异步数据流的——」

面试官:「你在 ChatGPT 吗?」

求职者:「没有啊——什么是 ChatGPT?」

面试官忽然从视频聊天界面里把头伸出屏幕,求职者吓一大跳,扶起椅子向后退一下:「诶!」面试官伸出来以后,回头看屏幕里的 ChatGPT。求职者在旁边安静地、不知所措地静静看着面试官。看了一会儿,面试官若有所思地、不置可否地:「Huh。」

开场

大家好,我是扔物线朱凯。

泛型是 Java 里一个很方便的特性,它的优势很多,其中之一就是提高了代码的复用能力,让我们只用写一个类或者接口或者方法,就能在调用时去应用到不同的类型:

java
代码解读
复制代码
List list1 = new ArrayList<>(); // String List list2 = new ArrayList<>(); // Integer List list3 = new ArrayList<>(); // Service TextView textView = findViewById(R.id.textView); // TextView ImageView imageView = findViewById(R.id.imageView); // ImageView

1.webp

2.webp

这种动态应用本来就很方便了,泛型还允许我们在调用时连类型都不用指定,而是让代码自动推断:

3.webp

4.webp

而 Kotlin 在沿袭了 Java 泛型的这些功能的同时,还进行了多项进化,其中就包括咱这期要聊的话题:它支持一种更强、更深的类型推断。

flow() 的类型推断

Java 的类型推断,是通过上下文信息来推断类型的。比如通过方法参数的类型来推断,或者通过赋值的目标变量的类型来推断:

5.webp

6.webp Kotlin 也可以做这类推断:

7.webp

另外,Kotlin 还能做一种加强的推断:它不仅能看函数的参数类型,还能钻进参数里,通过参数内部的内容来做更深的类型推断。什么叫参数内部呢?就是当你的参数是函数类型的时候:

8.webp

Kotlin 有能力钻到它的大括号的里面,去一行行分析里面的代码,来进行类型推断。 比如我如果只调用 flow {},它会报错,这是因为 flow() 是个泛型函数:

9.webp

而我既没有指明类型参数的类型,也没有给出足够的上下文让它去做类型推断。 如果我直接写明:

10.webp

它就不报错了。 或者,我也可以在大括号里生产一个 Flow 的元素:

11.webp

Kotlin 也可以从中推断出类型,所以也不会报错。 而这种推断,是 Java 所没有的。

@BuilderInference

它是怎么推断的呢? 它并不是对每一行代码都检查,而是只查看对 this 的每一次函数调用,通过这些调用来进行类型推断,然后把推断出的类型汇总之后得到外部函数的推断类型。 我这么说可能比较绕,我来举实际的例子。就还以 flow() 函数为例,它这个大括号,实际上是一个函数类型的参数,也就是这个:

12.webp

这个函数类型的参数,它的参数类型、返回值类型、是不是挂起函数,这些对类型推断都不重要:

13.webp

14.webp

15.webp 关键在于,它设置了一个 receiver 类型:

16.webp 这么写,可以让大括号里有一个这个类型的 this,也就是所谓的 implicit receiver,隐式的 receiver——关于「隐式的 receiver」这个概念,我上上条视频专门讲过,如果你没了解过可以去看一下——那么大括号里有了这个 FlowCollector 类型的 this,我就可以在里面调用它的函数,比如我这个 emit(),生产 Flow 元素的函数,其实就是它下面的:

17.webp

18.webp 然后呢,这个 FlowCollector 是一个泛型类型:

19.webp

而 emit() 的参数就是它的类型参数的类型,也就是这个 T:

20.webp

那么,Kotlin 就会在实际的调用中利用 emit() 的传入参数来作为推断出的实例化类型,也就是外面的 FlowCollector 的 T 的类型。比如我这里填入的是个字符串:

21.webp

那么 Kotlin 就会推断出这个 T 的类型是 String:

22.webp

这种推断其实比较特殊:典型的类型推断,是用对象的类型来得出函数的参数和返回值类型,比如用 FlowCollector 对象的实例化类型来推断出 emit() 的参数类型;而这个,它是反过来的,它是由函数调用来推断出对象的实例化类型,也就是由 emit() 的参数类型推断出 FlowCollector 的 T 的类型。 这个 FlowCollector 的 T,其实是用的 flow() 函数的类型参数。所以推断出了它的 T,也就等于推断出了 flow() 函数的 T。也就是对咱这个例子来说,flow() 函数的实例化类型就是 String:

23.webp 整个类型推断的逻辑,就是这样的。它不是直接看函数调用时的传入参数的类型,而是要求参数必须是函数类型的,然后去看这个函数类型的参数的内部代码,去进行类型推断:

24.webp 另外,Kotlin 还要求我们必须给这个参数设置一个 receiver 类型:

25.webp 并且,这个 receiver 还需要是泛型类型的,同时我们还要用函数的类型参数来作为它的实例化类型——或者直白地说,就是要把这个 T 写在这里:

26.webp 这样,整个链条就全都接上了,从技术的角度,我们就可以让 Kotlin 通过在大括号里对 this 的调用来推断类型了。 而在实操的角度,Kotlin 还有一个语法上的额外要求:我们还要给参数加上一个叫 BuilderInference 的注解:

27.webp

因为这种推断默认是不开启的,我们需要加上这个 @BuilderInference 来手动开启它。为什么这么设计?一般是出于向前兼容性、代码的复杂性和可读性以及编译性能之类的综合考虑——具体我不知道,没考证过。

多次调用和综合推断

咱写的是大括号里只有一次函数调用,那么就只有一次类型推断:

28.webp

而如果我们进行多次调用,Kotlin 会对多次调用的结果进行综合之后,得出统一的推断类型:

29.webp

总结

Kotlin 跟 Java 相比,最大的改动之一就是它增加了「函数类型」的概念,这种概念上的突破给语言增加了很多灵活性。比如这个 BuilderInference,它本质上是借助对函数类型的对象的内部代码进行查看,来实现的一种间接的——或者说路径更长的——类型推断。 Kotlin 的标准库、协程以及各种第三方库——比如 Jetpack Compose——都有不少对于这个特性的使用,它可以让我们很方便地写一些通用的功能函数。如果你在公司或者团队里负责基础架构的搭建,或者你是某些开源库的作者,它很可能会对你有帮助。 行,今天就这么多。关注我,了解更多开发知识和技能。我是扔物线,我不和你比高低,我只助你成长。我们下期见!

注:本文转载自juejin.cn的扔物线的文章"https://juejin.cn/post/7439931420523069479"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

140
Android
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top