diff --git a/.gitignore b/.gitignore index e48dcab..1f8b693 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ build .idea out raw -cache \ No newline at end of file +cache +beta \ No newline at end of file diff --git a/README.md b/README.md index eb01347..b58db0c 100644 --- a/README.md +++ b/README.md @@ -1,137 +1,83 @@ -# [Kotlin从入门到『放弃』系列 视频教程](https://github.com/enbandari/Kotlin-Tutorials) +[![GitHub license](https://img.shields.io/badge/license-CC%20BY--NC--ND%204.0-blue.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) -随着Kotlin越来越成熟稳定,我已经开始在生产环境中使用它。考虑到目前国内资料较少,近期我开始筹划录制一套视频教程,并以此抛砖引玉,让 Kotlin 在国内火起来。 +# Kotlin-Tutorials -个人水平有限,不足之处欢迎大家发邮件到 [bennyhuo@println.net](mailto: bennyhuo@println.net),谢谢大家! +**2021.6 更新** -# 发布计划 +这个仓库最初(2016年底)是用来分享一些 Kotlin 教程的,感兴趣的话可以查看[这里](legacy/README.md)。后来随着 Google 的大力支持,Kotlin 已经逐步在 Android 开发领域占据了一席之地。我就以个人经历来说说自己的感受吧: -关注微信公众号:Kotlin, 获取最新视频更新动态 +过去几年我所在的[腾讯公司](https://www.tencent.com)当中,Kotlin 的落地项目实际上已经相当可观,例如: +* 外部开源的 Android 插件化框架 [Shadow](https://github.com/Tencent/Shadow),核心逻辑基本上使用 Kotlin 编写。 +* [蓝鲸 CI 平台](https://github.com/Tencent/bk-ci),这是一个后端项目,在腾讯内部已经成为公司主推的 CI 平台,之前我在上面做持续集成时需要做插件开发,惊喜地发现打印出来的调用堆栈居然有 Kotlin 身影。 +* 内部还有团队使用 KMM 做跨平台的 UI 控件渲染,这可以说是非常有挑战的工作了,不仅要在移动端支持 Android、iOS,还要同时支持桌面版。基于这个框架所属产品的体量,我们大概率已经是这套技术方案的用户了。 - +今年初我因个人原因离开了鹅厂,去了[北京猿力科技有限公司(猿辅导/看云集团)](https://www.kanyun.com/),不出所料,在这家号称**小而美**且**有技术追求**的公司当中,Kotlin 在项目上的应用已经相当广泛了,新代码很少能见到 Java 的身影(有需要内推的小伙伴可以找我)。 + +所以,作为“布道者”,过去我们总是想着怎么让更多的开发者知道 Kotlin,现在我们则需要提供更多的 Kotlin 的学习材料,来帮助大家更好的使用 Kotlin。 -从10月初开始,每期视频控制在10-20分钟,更新间隔视情况而定,尽量在每周能至少更新一期。 +我目前主要的想法就是做一些视频放到 B 站上(账号:[**bennyhuo 不是算命的**](https://space.bilibili.com/28615855)),当然视频的内容也不限于 Kotlin 本身。 -* 10月14日:思考了一下,我决定将视频的内容调整为几个案例,而不是传统的教条式的讲述,因为。。我录得时候发现我自己都困了哈哈 +有想法的小伙伴欢迎与我交流,也欢迎加微信群,请先添加微信好友 **bennyhuo007**,暗号“**好家伙**”,我拉你进群 - [在线收看全部视频(腾讯视频)](http://v.qq.com/boke/gplay/903446d6231d8612d198c58fb86eb4dc_t6d000101bd9lx1.html) - - [下载全部视频(百度云)](http://pan.baidu.com/s/1nvGYAfB) +## 内容清单 -* 11月6日:大家有什么关心的技术点也可以在issue里面发出来一起讨论哈,我也会根据大家的需求来安排后面的内容。 -* 11月28日:有朋友问我,为什么要『放弃』。。。额,这是一个用来自嘲的梗嘛,大家不信去搜搜 『Java 从入门到放弃』 :) -* 12月2日:有朋友说内容太少啦,不够看!我首先要表示一下感谢,谢谢诸位的关注和支持~这套视频是我在工作之余抽时间录制的,一个视频虽然只有10分钟,不过内容点却不太好想,通常一个视频我会尝试准备几个点,最终选择一个合适的录制,所以更新速度不会太快,不过,我会尽量保证在每周一更新一期,说实话我也挺着急,哈哈~还有一个事情就是,编程语言这个东西本身并不难,难的是它身后的一大家子(生态),Kotlin 的身后就是积累多年的 Java 生态,如果大家对视频有疑问,尽管发邮件或者直接开 issue 跟我讨论,我也可以考虑录一些『番外篇』来解答这些问题,谢谢大家的支持! -* 12月19日:这一套视频从一开始也没有明确的大纲,我只是希望能讲一些网络上的文章不怎么提到的一些细节,或者分享一些我觉得有意思的话题。我想了一下,有了下面这几期,大家基本上可以入手尝试自己写点儿什么了,这样我的目的也就达到了。公众号还会持续推送 Kotlin 有意思的话题,请大家关注~ **基础部分已完结。** +内容清单已迁移至我的个人主页:[Benny Huo 的专栏](https://www.bennyhuo.com/book/)。 -# 目录 +## 联系我 -##第一部分 语言基础(已完结) +* 邮箱: [bennyhuo@kotliner.cn](mailto:bennyhuo@kotliner.cn) +* B 站账号:[**bennyhuo 不是算命的**](https://space.bilibili.com/28615855),我的个人视频会优先在 B 站发布 +* 微信公众号 **bennyhuo** +--- -####[01 Kotlin 简介](http://v.qq.com/page/z/u/9/z0337i7a3u9.html) +以下是过去几年我的一些积累和产出,有兴趣可以关注。 -  简要介绍下什么是 Kotlin,新语言太多了,大家为什么要接触 Kotlin 呢?因为它除了长得与 Java 不太像以外,其他的都差不多~ - -####[02 Hello World](http://v.qq.com/page/h/n/m/h0337jfa5nm.html) +## [《深入实践 Kotlin 元编程》](https://www.bennyhuo.com/project/kotlin-metaprogramming.html) 2023.9 出版 -  千里之行,始于Hello World! - -####[03 使用Gradle编写程序简介(可选)](http://v.qq.com/page/b/p/l/b03372ox4pl.html) +这是一本从基础知识、设计思想、技术方案、应用方法、实践技巧5个维度系统讲解Kotlin元编程,并以此大幅提升Kotlin工程师开发水平、研发效率和开发体验的著作。 -  这年头,写 Java 系的代码,不知道 Gradle 怎么行呢? - -####[04 集合遍历 map](http://v.qq.com/page/s/q/c/s033707mdqc.html) +本书的出版打破了元编程技术资料少、门槛高的行业现状。本书包含大量案例,这些案例大多来自真实的生产实践,相对成熟和完善,可以作为元编程项目的范本。同时,本书提供大量的代码,为了提升阅读体验,在注释、书写和排版等方面对代码做了精心的优化。 -  放下 i++,你不知道 map 已经占领世界了么?以前我以为 map-reduce 很牛逼,后来才知道就是数据迭代处理嘛。 - -####[05 集合扁平化 flatMap](http://v.qq.com/page/h/u/7/h0337scgau7.html) +## 随书源码 -  这个可以说是 map 的一个加强版,返回的仍然是开一个可迭代的集合,用哪个您自己看需求~ - -####[06 枚举类型与When表达式](http://v.qq.com/page/t/0/9/t0337iacg09.html) +本书**源码地址**:[《深入实践 Kotlin 元编程》源码](https://github.com/bennyhuo/KotlinMetaProgrammingInAction-Sources) -  Kotlin 丢掉了 switch,却引进了 when,这二者看上去极其相似,不过后者却要强大得多。至于枚举嘛,还是 Java 枚举的老样子。 - -####[07 在 RxJava 中使用 Lambda](http://v.qq.com/x/page/l0340boeng7.html) +## 购买途径 -  这一期通过一个统计文章中字符数的小程序进一步给大家呈现 Lambda 的威力,也向大家展示一下如何在 Kotlin 当中优雅地使用 RxJava。我不做教科书,所以如果大家对概念感兴趣,可以直接阅读官方 [API](https://kotlinlang.org/docs/reference/lambdas.html) +* 京东自营:[深入实践 Kotlin 元编程](https://item.jd.com/14097194.html) +* 当当自营:[深入实践 Kotlin 元编程](https://product.dangdang.com/29613442.html) -  [RxJava](https://github.com/ReactiveX/RxJava) 是一个非常流行的 Java Reactive 框架,函数式的数据操作使得 Lambda 表达式可以充分体现自己的优势,比起 Java 的冗长,你会看到一段非常漂亮简洁的代码。建议大家先阅读 [RxJava](https://github.com/ReactiveX/RxJava) 的官方文章以对其有一些基本的认识。 +## [《深入理解 Kotlin 协程》](https://www.bennyhuo.com/project/kotlin-coroutines.html) 2020.6 出版 -####[08 使用 Retrofit 发送 GET 请求](http://v.qq.com/x/page/t0342thu1al.html) -  [Retrofit](https://square.github.io/retrofit/) 是 Square 的 Jake 大神开源的RESTful 网络请求框架,用它发送请求的感觉会让你感觉爽爆的。我这里还有几篇文章,以及一个我 hack 过的分支 [HackRetrofit](https://github.com/enbandari/HackRetrofit),有兴趣的童鞋可以一起探讨下~ +Kotlin 协程可以说是截止目前为止 Kotlin 中最让人困惑的一部分内容了,官方文档也比较简略,对于初学者不够友好。今年我把过去在公众号和博客发布的协程相关的文章进行了整理和扩充,进一步完善了诸多细节编写了本书,有兴趣可以留意一下。 +### 随书源码 -* [Android 下午茶:Hack Retrofit 之 增强参数](http://www.println.net/post/Android-Hack-Retrofit). +本书**源码地址**:[《深入理解 Kotlin 协程》源码](https://github.com/bennyhuo/DiveIntoKotlinCoroutines-Sources) -* [Android 下午茶:Hack Retrofit (2) 之 Mock Server](http://www.println.net/post/Android-Hack-Retrofit-Mock-Server) +### 购买途径 -* [深入浅出 Retrofit,这么牛逼的框架你们还不来看看?](http://www.println.net/post/deep-in-retrofit) +* 京东自营:[深入理解Kotlin协程](https://item.jd.com/12898592.html) +* 当当自营:[深入理解Kotlin协程](http://product.dangdang.com/28973005.html) -####[09 尾递归优化](http://v.qq.com/x/page/f0345wmuw2m.html) -  尾递归,顾名思义,就是递归中调用自身的部分在函数体的最后一句。我们知道,递归调用对于栈大小的考验是非常大的,也经常会因为这个导致 StackOverflow,所以尾递归优化也是大家比较关注的一个话题。Kotlin 支持语法层面的尾递归优化,这在其他语言里面是不多见的。 +## [注解处理器开发教程](https://github.com/bennyhuo/Apt-Tutorials) -####[10 单例](https://v.qq.com/x/page/f034839rf5q.html) +我在做 [基于 GitHub App 业务深度讲解 Kotlin1.2高级特性与框架设计](https://coding.imooc.com/class/232.html)(目前已经下线) 这门课的时候,顺便做了一个注解处理器的框架,叫 [Tieguanyin(铁观音)](https://github.com/bennyhuo/TieGuanYin),这个框架主要是用来解决 Activity 跳转时传参的问题,我们知道 Activity 如果需要参数,那么我们只能非常繁琐的使用 `Intent` 来传递,有了这个框架我们就可以省去这个麻烦的步骤。 -  单例大家一定都不陌生,只要你动手写一个程序,就免不了要设计出一些全局存在且唯一的对象,他们就适合采用单例模式编写。在 Java 里面,单例模式的写法常见的有好几种,虽然简单却也是涉及了一些有意思的话题,那么在 Kotlin 当中我们要怎么设计单例程序呢? +在这里,框架的内容其实不是重点,重点是,它是一个注解处理器的项目。为了让它的作用尽可能的放大,我对原框架做了简化,做了这套课程。 -####[11 Sealed Class](https://v.qq.com/x/page/f0350ioskzj.html) -  枚举类型可以很好的限制一个类型的实例个数,比如 State 枚举有两种类型 IDLE 和 BUSY 两种状态,用枚举来描述再合适不过。不过,如果你想要设计子类个数有限的数据结构,比如指令,指令的类型通常是确定的,不过对于某些有参数的指令每一次都使用同一个实例反而不合适,这时候就需要 Sealed Class。 -   -####[12 Json数据引发的血案](https://v.qq.com/x/page/s035296s9nw.html) -  Json 数据可真是大红大紫一番,它实在是太容易理解了,随着 Js 的火爆它就更加『肆无忌惮』起来。我们在 Java/Kotlin 当中解析它的时候经常会用到 Gson 这个库,用它来解析数据究竟会遇到哪些问题?本期主要围绕 Json 解析的几个小例子,给大家展示一下 Java/Kotlin 的伪泛型设计的问题,以及不完整的数据的解析对语言本身特性的冲击。 +## [Kotlin 从入门到精通 视频教程](http://coding.imooc.com/class/398.html) -####[13 kapt 以及它的小伙伴们](https://v.qq.com/x/page/q035439xksx.html) -  首先感谢 @CodingPapi,这一期的内容主要来自于他的建议。 +Kotlin 1.3 是一个相对成熟和稳定的版本,这次基于 Kotlin 1.3.50 重新制作入门到精通的课程,相比之下新课知识点梳理更详细,内容干货更多,讲法也更成熟,希望能对大家有帮助。 -  Kotiln 对于注解的支持情况在今年(2016)取得了较大的成果,现在除了对 @Inherited 这个注解的支持还不够之外,试用了一下没有发现太大的问题。关于 kapt,官方的文章罗列下来,其中 +**视频地址:** [http://coding.imooc.com/class/398.html](http://coding.imooc.com/class/398.html) -* [kapt: Annotation Processing for Kotlin -](https://blog.jetbrains.com/kotlin/2015/05/kapt-annotation-processing-for-kotlin/) 已经过时了,大家可以阅读下了解其中提到的三个方案 -* [Better Annotation Processing: Supporting Stubs in kapt -](https://blog.jetbrains.com/kotlin/2015/06/better-annotation-processing-supporting-stubs-in-kapt/) 提到的实现其实基本上就是现在的正式版 +## [破解 Retrofit](https://www.imooc.com/learn/1128?mc_marking=5487b137ad904bd13590a053ede6da2f&mc_channel=syb19) -* [Kotlin 1.0.4 is here -](https://blog.jetbrains.com/kotlin/2016/09/kotlin-1-0-4-is-here/)提到了 kapt 的正式发布,需要注意的是,kapt 的使用方法有些变化,需要 ```apply plugin: 'kotlin-kapt'``` +最近不少朋友反馈希望能看到一些深入分析框架的课程,正好前段时间对 Retrofit 又做了一次深入的分析,整理了一套免费视频分享给大家~ -  本期主要通过一个简单的 [Dagger2](https://google.github.io/dagger/) 实例给大家展示了注解在 Kotlin 当中的使用,看上去其实与在 Java 中使用区别不大,生成的源码也暂时是 Java 代码,不过这都不重要了,反正是要编译成 class 文件的。 +## [破解Android高级面试](https://s.imooc.com/SBS30PR) -  后面我们又简单分析了一下 Dagger2 以及 [ButterKnife](https://github.com/JakeWharton/butterknife) 的源码(有兴趣的话也可以看下我直接对后者进行分析和 Hack 的一篇文章:[深入浅出 ButterKnife,听说你还在 findViewById?](http://www.println.net/post/Deep-in-ButterKnife-3)),其实自己实现一个注解处理器是非常容易的,类似的框架还有[androidannotations](https://github.com/androidannotations/androidannotations),它的源码大家可以自行阅读。 - -**** -通过这个例子,我们其实发现 kapt 还是有一些不完善的地方,主要是: - -1. 不支持 @Inherited -2. 生成的源码需要手动添加到 SourceSets 中 -3. 编译时有时候需要手动操作一下 gradle 的 build 才能生成源码(这一点大家注意下就行了,我在视频中并没有提到) - -不过总体来讲,kapt 的现状还是不错的,相信不久的将来这些问题都将不是问题。 -**** - -#### [14 Kotlin 与 Java 共存 (1)](https://v.qq.com/x/page/c03579nzo8x.html) - -  你想要追求代码简洁、美观、精致,你应该倾向于使用 Kotlin,而如果你想要追求代码的功能强大,甚至有些黑科技的感觉,那 Java 还是当仁不让的。 - -  说了这么多,还是那句话,让他们共存,各取所长。 - -  那么问题来了,怎么共存呢?虽然一说理论我们都知道,跑在 Jvm 上面的语言最终都是要编成 class 文件的,在这个层面大家都是 Java 虚拟机的字节码,可他们在编译之前毕竟还是有不少差异的,这可如何是好? - -  正所谓兵来将挡水来土掩,有多少差异,就要有多少对策,这一期我们先讲**在 Java 中调用 Kotlin**。 - - -#### [15 Kotlin 与 Java 共存 (2)](https://v.qq.com/x/page/z0357ls85fe.html) - -  上一期我们简单讨论了几个 Java 调用 Kotlin 的场景,这一期我们主要讨论相反的情况:如何在 Kotlin 当中调用 Java 代码。 - -  除了视频中提到的点之外还有一些细节,比如异常的捕获,集合类型的映射等等,大家自行参考官方文档即可。在了解了这些之后,你就可以放心大胆的在你的项目中慢慢渗透 Kotlin,让你的代码逐渐走向简洁与精致了。 - - -## 第二部分 使用 Kotlin 进行 Android 开发(待定) - - -# 打赏 - -录制这样一套视频确实是需要花费时间和心血的,如果您觉得它对您有帮助,可以通过微信和支付宝打赏,我将努力将视频做到最好!谢谢! - - +我一直做 Kotlin 的推广和宣传,发现大多数学习 Kotlin 的同学都是被行业“胁迫”不得不学。大家的诉求更多是怎么样找到一份好的工作,考虑到学习 Kotlin 的同学大多都是 Android 开发者,我就花了半年的功夫仔细整理了这一套视频出来,题目看上去不多,但每一个题目背后能引出的知识点可一点儿都不少。不求面面俱到,只求精准打击,面试过程中只要你能给面试官留下深刻的印象,那么这事儿就成了。 diff --git a/code/Kotlin-Sample/.gitignore b/code/Kotlin-Sample/.gitignore new file mode 100644 index 0000000..6ea006e --- /dev/null +++ b/code/Kotlin-Sample/.gitignore @@ -0,0 +1,5 @@ +.idea +.gradle +*.iml +local.properties +build \ No newline at end of file diff --git a/code/Kotlin-Sample/Kotlin-mpp-sample/build.gradle.kts b/code/Kotlin-Sample/Kotlin-mpp-sample/build.gradle.kts new file mode 100644 index 0000000..0ce2de7 --- /dev/null +++ b/code/Kotlin-Sample/Kotlin-mpp-sample/build.gradle.kts @@ -0,0 +1,39 @@ +plugins { + kotlin("multiplatform") +} + +group = "com.bennyhuo.kotlin.hello" +version = "1.0-SNAPSHOT" + +kotlin { + /* Targets configuration omitted. + * To find out how to configure the targets, please follow the link: + * https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets */ + + sourceSets { + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + + jvm() + js{ + nodejs() + } + mingwX64 { + binaries { + executable { + // Binary configuration. + entryPoint = "com.bennyhuo.kotlin.sample.main" + } + } + } + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/Kotlin-mpp-sample/src/mingwX64Main/kotlin/com/bennyhuo/kotlin/sample/Main.kt b/code/Kotlin-Sample/Kotlin-mpp-sample/src/mingwX64Main/kotlin/com/bennyhuo/kotlin/sample/Main.kt new file mode 100644 index 0000000..c60dc56 --- /dev/null +++ b/code/Kotlin-Sample/Kotlin-mpp-sample/src/mingwX64Main/kotlin/com/bennyhuo/kotlin/sample/Main.kt @@ -0,0 +1,24 @@ +package com.bennyhuo.kotlin.sample + +/** + * Created by benny. + */ + +interface DeepCopyable + +data class District(var name: String) + +data class Location(var lat: Double, var lng: Double) + +data class Company(var name: String, var location: Location, var district: District): DeepCopyable + +data class Speaker(var name: String, var age: Int, var company: Company): DeepCopyable + +data class Talk(var name: String, var speaker: Speaker): DeepCopyable + + +fun main() { + println("Hello") + + val district = District("x") +} \ No newline at end of file diff --git a/code/Kotlin-Sample/build.gradle.kts b/code/Kotlin-Sample/build.gradle.kts new file mode 100644 index 0000000..5e00a50 --- /dev/null +++ b/code/Kotlin-Sample/build.gradle.kts @@ -0,0 +1,75 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +buildscript { + repositories { + maven("https://mirrors.tencent.com/nexus/repository/maven-public/") + } + dependencies { + classpath("com.android.tools.build:gradle:4.1.3") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + } +} + +plugins { + java + kotlin("jvm") version kotlinVersion + id("test-plugin") + id("com.bennyhuo.test-plugin") +} + +group = "com.bennyhuo.kotlin.hello" +version = "1.0-SNAPSHOT" + +allprojects { + repositories { + maven("https://mirrors.tencent.com/nexus/repository/maven-public/") + } +} + +dependencies { + implementation(kotlin("stdlib")) + implementation(kotlin("reflect")) + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutineVersion") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlinCoroutineVersion") + + implementation("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinDateTimeVersion") + + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("com.squareup.retrofit2:adapter-rxjava3:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") + implementation("com.bennyhuo:portable-android-handler:1.0") + implementation("io.reactivex.rxjava3:rxjava:3.0.13") + + implementation("org.apache.logging.log4j:log4j-core:2.14.1") + implementation("org.apache.logging.log4j:log4j-api:2.14.1") + + implementation(project(":opt-in-sample")) + implementation(project(":deprecated-sample")) + + testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") +} + +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + freeCompilerArgs = listOf( + "-Xopt-in=kotlin.RequiresOptIn", + "-Xextended-compiler-checks", + "-Xenable-builder-inference" + ) + jvmTarget = "17" +} + +java { + targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_17 +} + +//tasks.withType().forEach { +// it.options.compilerArgs.add("--enable-preview") +//} + +tasks.getByName("test") { + useJUnitPlatform() +} \ No newline at end of file diff --git a/code/Kotlin-Sample/buildSrc/build.gradle.kts b/code/Kotlin-Sample/buildSrc/build.gradle.kts new file mode 100644 index 0000000..28c68a8 --- /dev/null +++ b/code/Kotlin-Sample/buildSrc/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + `kotlin-dsl` + //region + //id("org.gradle.kotlin.kotlin-dsl") version "2.1.4" + //endregion +} + +repositories { + maven("https://mirrors.tencent.com/nexus/repository/maven-public/") +} + +gradlePlugin { + plugins { + create("TestPlugin") { + id = "com.bennyhuo.test-plugin" + implementationClass = "TestPlugin" + } + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/buildSrc/src/main/kotlin/TestPlugin.kt b/code/Kotlin-Sample/buildSrc/src/main/kotlin/TestPlugin.kt new file mode 100644 index 0000000..f29dcdc --- /dev/null +++ b/code/Kotlin-Sample/buildSrc/src/main/kotlin/TestPlugin.kt @@ -0,0 +1,11 @@ +import org.gradle.api.Plugin +import org.gradle.api.Project + +/** + * Created by benny. + */ +class TestPlugin: Plugin { + override fun apply(target: Project) { + println("Test Plugin applied!") + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/buildSrc/src/main/kotlin/Versions.kt b/code/Kotlin-Sample/buildSrc/src/main/kotlin/Versions.kt new file mode 100644 index 0000000..d1ec443 --- /dev/null +++ b/code/Kotlin-Sample/buildSrc/src/main/kotlin/Versions.kt @@ -0,0 +1,3 @@ +val kotlinVersion = "1.6.0" +val kotlinCoroutineVersion = "1.6.0-RC" +val kotlinDateTimeVersion = "0.3.1" \ No newline at end of file diff --git a/code/Kotlin-Sample/buildSrc/src/main/kotlin/test-plugin.gradle.kts b/code/Kotlin-Sample/buildSrc/src/main/kotlin/test-plugin.gradle.kts new file mode 100644 index 0000000..ee9fa3c --- /dev/null +++ b/code/Kotlin-Sample/buildSrc/src/main/kotlin/test-plugin.gradle.kts @@ -0,0 +1,7 @@ +tasks.register("hello") { + println("Register task hello.") + group = "test" + doLast { + println("Hello Task from precompiled task.") + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/deprecated-sample/build.gradle.kts b/code/Kotlin-Sample/deprecated-sample/build.gradle.kts new file mode 100644 index 0000000..1642f91 --- /dev/null +++ b/code/Kotlin-Sample/deprecated-sample/build.gradle.kts @@ -0,0 +1,27 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + java + kotlin("jvm") +} + +group = "com.bennyhuo" +version = "1.0-SNAPSHOT" + +repositories { + maven("https://mirrors.tencent.com/nexus/repository/maven-public/") +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0") +} + +tasks.getByName("compileKotlin") { + kotlinOptions.freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn") +} + +tasks.getByName("test") { + useJUnitPlatform() +} \ No newline at end of file diff --git a/code/Kotlin-Sample/deprecated-sample/src/main/java/com/bennyhuo/kotlin/deprecatedsample/Api.kt b/code/Kotlin-Sample/deprecated-sample/src/main/java/com/bennyhuo/kotlin/deprecatedsample/Api.kt new file mode 100644 index 0000000..7691b53 --- /dev/null +++ b/code/Kotlin-Sample/deprecated-sample/src/main/java/com/bennyhuo/kotlin/deprecatedsample/Api.kt @@ -0,0 +1,20 @@ +package com.bennyhuo.kotlin.deprecatedsample + +object Api { + + fun newApiForDeprecated(key: String, value: String) { + + } + + @Deprecated( + message = "Use newApiForDeprecated instead.", + replaceWith = ReplaceWith( + expression = "NewApi.newApiForDeprecated(key, value, default)", + imports = ["com.bennyhuo.kotlin.deprecatedsample.v2.NewApi"] + ) + ) + fun deprecatedDontUse(key: String, value: String) { + + } + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/deprecated-sample/src/main/java/com/bennyhuo/kotlin/deprecatedsample/v2/NewApi.kt b/code/Kotlin-Sample/deprecated-sample/src/main/java/com/bennyhuo/kotlin/deprecatedsample/v2/NewApi.kt new file mode 100644 index 0000000..fe71f2e --- /dev/null +++ b/code/Kotlin-Sample/deprecated-sample/src/main/java/com/bennyhuo/kotlin/deprecatedsample/v2/NewApi.kt @@ -0,0 +1,9 @@ +package com.bennyhuo.kotlin.deprecatedsample.v2 + +object NewApi { + + fun newApiForDeprecated(key: String, value: String, default: String) { + + } + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/gradle.properties b/code/Kotlin-Sample/gradle.properties new file mode 100644 index 0000000..94b6fbc --- /dev/null +++ b/code/Kotlin-Sample/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +org.gradle.daemon=true \ No newline at end of file diff --git a/code/Kotlin-Sample/gradle/wrapper/gradle-wrapper.jar b/code/Kotlin-Sample/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/code/Kotlin-Sample/gradle/wrapper/gradle-wrapper.jar differ diff --git a/code/Kotlin-Sample/gradle/wrapper/gradle-wrapper.properties b/code/Kotlin-Sample/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..fbce071 --- /dev/null +++ b/code/Kotlin-Sample/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/code/Kotlin-Sample/gradlew b/code/Kotlin-Sample/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/code/Kotlin-Sample/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/code/Kotlin-Sample/gradlew.bat b/code/Kotlin-Sample/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/code/Kotlin-Sample/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/code/Kotlin-Sample/kclass-issue/build.gradle.kts b/code/Kotlin-Sample/kclass-issue/build.gradle.kts new file mode 100644 index 0000000..4bf1f04 --- /dev/null +++ b/code/Kotlin-Sample/kclass-issue/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + java + kotlin("jvm") +} + +group = "com.bennyhuo.kotlin.hello" +version = "1.0-SNAPSHOT" + +dependencies { + implementation(kotlin("stdlib")) + implementation(kotlin("reflect")) + testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") +} + +tasks.getByName("test") { + useJUnitPlatform() +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kclass-issue/src/main/java/com/bennyhuo/kotlin/kclassvalue/Main.kt b/code/Kotlin-Sample/kclass-issue/src/main/java/com/bennyhuo/kotlin/kclassvalue/Main.kt new file mode 100644 index 0000000..7a58b3b --- /dev/null +++ b/code/Kotlin-Sample/kclass-issue/src/main/java/com/bennyhuo/kotlin/kclassvalue/Main.kt @@ -0,0 +1,38 @@ +package com.bennyhuo.kotlin.kclassvalue + +import kotlin.concurrent.thread + +/** + * Created by benny. + */ +fun main() { +// val anyClass = Any::class +// val anyClass2 = Any::class +// println(anyClass == anyClass2) +// println(anyClass === anyClass2) + + testConcurrentIssue() +} + +//region concurrent issue. +var concurrentValue = 0 + +fun safeIncrement() { + synchronized(Any::class) { + concurrentValue++ + } +} + +fun testConcurrentIssue() { + List(100) { + thread(start = false) { + for (i in 0 until 1000) { + safeIncrement() + } + } + }.onEach(Thread::start) + .forEach(Thread::join) + + println(concurrentValue) +} +//endregion \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/.gitignore b/code/Kotlin-Sample/kotlin-android-sample/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/build.gradle.kts b/code/Kotlin-Sample/kotlin-android-sample/build.gradle.kts new file mode 100644 index 0000000..108e17c --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/build.gradle.kts @@ -0,0 +1,52 @@ +plugins { + id("com.android.application") + id("kotlin-android") + id("kotlin-android-extensions") +} + +android { + compileSdkVersion(30) + buildToolsVersion ("30.0.3") + + defaultConfig { + applicationId = "com.bennyhuo.kotlin.android.sample" + minSdkVersion(16) + targetSdkVersion(30) + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner("android.support.test.runner.AndroidJUnitRunner") + } + + buildTypes { + val release by getting { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + useOldBackend = true + } +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutineVersion") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutineVersion") + + implementation("androidx.appcompat:appcompat:1.3.0") + implementation("androidx.constraintlayout:constraintlayout:2.0.4") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1") + + api("org.slf4j:slf4j-api:1.7.30") + api("com.github.tony19:logback-android:2.0.0") + + testImplementation("junit:junit:4.+") + androidTestImplementation("com.android.support.test:runner:1.0.2") + androidTestImplementation("com.android.support.test.espresso:espresso-core:3.0.2") +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/gradle.properties b/code/Kotlin-Sample/kotlin-android-sample/gradle.properties new file mode 100644 index 0000000..646c51b --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/gradle.properties @@ -0,0 +1,2 @@ +android.useAndroidX=true +android.enableJetifier=true diff --git a/code/Kotlin-Sample/kotlin-android-sample/proguard-rules.pro b/code/Kotlin-Sample/kotlin-android-sample/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/androidTest/java/com/bennyhuo/kotlin/android/sample/ExampleInstrumentedTest.kt b/code/Kotlin-Sample/kotlin-android-sample/src/androidTest/java/com/bennyhuo/kotlin/android/sample/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..5f627d2 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/androidTest/java/com/bennyhuo/kotlin/android/sample/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.bennyhuo.kotlin.android.sample + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.bennyhuo.kotlin.android.sample", appContext.packageName) + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/AndroidManifest.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d2a8aa2 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/assets/logback.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/assets/logback.xml new file mode 100644 index 0000000..e7cb5ba --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/assets/logback.xml @@ -0,0 +1,13 @@ + + + + + + [%thread](%file:%line\)%M: %msg%n + + + + + + + diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/java/com/bennyhuo/kotlin/android/sample/KaeTestActivity.kt b/code/Kotlin-Sample/kotlin-android-sample/src/main/java/com/bennyhuo/kotlin/android/sample/KaeTestActivity.kt new file mode 100644 index 0000000..c986184 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/java/com/bennyhuo/kotlin/android/sample/KaeTestActivity.kt @@ -0,0 +1,24 @@ +package com.bennyhuo.kotlin.android.sample + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import kotlinx.android.synthetic.main.activity_main.* +import org.slf4j.LoggerFactory + +class KaeTestActivity : AppCompatActivity() { + private val logger = LoggerFactory.getLogger(KaeTestActivity::class.java) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + textView.text = "hello" + textView.setOnClickListener { + logger.debug("clicked.") + } + + textView?.setOnClickListener { + + } + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/java/com/bennyhuo/kotlin/android/sample/MainActivity.kt b/code/Kotlin-Sample/kotlin-android-sample/src/main/java/com/bennyhuo/kotlin/android/sample/MainActivity.kt new file mode 100644 index 0000000..48e7f35 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/java/com/bennyhuo/kotlin/android/sample/MainActivity.kt @@ -0,0 +1,56 @@ +package com.bennyhuo.kotlin.android.sample + +import android.animation.ObjectAnimator +import android.os.Bundle +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch +import org.slf4j.LoggerFactory + +class MainActivity : AppCompatActivity() { + private val logger = LoggerFactory.getLogger(MainActivity::class.java) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + lifecycleScope.launch { + getTextViewPositionFlow() + .collect { + logger.debug(it.toString()) + } + } + + textView.setOnClickListener { + ObjectAnimator.ofFloat(textView, "x", 0f, 1000f) + .setDuration(1000) + .start() + + ObjectAnimator.ofFloat(textView, "y", 0f, 500f) + .setDuration(1000) + .start() + } + } + + private fun getTextViewPositionFlow(): Flow> { + return callbackFlow> { + val listener = + View.OnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom -> + logger.debug("left: $left, top: $top") + trySendBlocking(top to left) + } + textView.addOnLayoutChangeListener(listener) + + awaitClose { + textView.removeOnLayoutChangeListener(listener) + } + } + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1babaae --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/drawable/ic_launcher_background.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..f9a2c5a --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/layout/activity_main.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..ca40db6 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/layout/activity_main.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-hdpi/ic_launcher.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..61da551 Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-mdpi/ic_launcher.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..db5080a Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..da31a87 Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b216f2d Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..e96783c Binary files /dev/null and b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values-night/themes.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..06d5d58 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values-night/themes.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/colors.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/strings.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/strings.xml new file mode 100644 index 0000000..f7bbc04 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Kotlin-Android-Sample + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/themes.xml b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/themes.xml new file mode 100644 index 0000000..40bb80f --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/main/res/values/themes.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-android-sample/src/test/java/com/bennyhuo/kotlin/android/sample/ExampleUnitTest.kt b/code/Kotlin-Sample/kotlin-android-sample/src/test/java/com/bennyhuo/kotlin/android/sample/ExampleUnitTest.kt new file mode 100644 index 0000000..4680ac5 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-android-sample/src/test/java/com/bennyhuo/kotlin/android/sample/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.bennyhuo.kotlin.android.sample + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-js-sample/build.gradle.kts b/code/Kotlin-Sample/kotlin-js-sample/build.gradle.kts new file mode 100644 index 0000000..4c612e4 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-js-sample/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + id("org.jetbrains.kotlin.js") +} + +group = "com.bennyhuo.kotlin.hello" +version = "1.0-SNAPSHOT" + +dependencies { + implementation(kotlin("stdlib-js")) +} + +kotlin { +// js(IR) { +// moduleName = "kotlin-js-ir" +// binaries.executable() +// nodejs() +// } + + js { + moduleName = "kotlin-js-legacy" + binaries.executable() + nodejs() + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/Main.kt b/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/Main.kt new file mode 100644 index 0000000..1ac2f52 --- /dev/null +++ b/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/Main.kt @@ -0,0 +1,56 @@ +package com.bennyhuo.kotlin.js + +import com.bennyhuo.kotlin.js.deepcopy.DeepCopyable +import com.bennyhuo.kotlin.js.deepcopy.deepCopy +import com.bennyhuo.kotlin.js.kclassvalue.testKClass + +/** + * Created by benny at 2021/6/26 8:36. + */ +fun main() { + console.log("Hello Js") + + val duration = Duration(10) + println(duration) + + testKClass() + + val talk = Talk( + "如何优雅地使用数据类", + Speaker( + "bennyhuo 不是算命的", + 1, + Company( + "猿辅导", + Location(39.9, 116.3), + District("北京郊区") + ) + ) + ) + + val copiedTalk = talk.deepCopy() +// copiedTalk.name = "Kotlin 编译器插件:我们不期待" +// copiedTalk.speaker.company = Company( +// "猿辅导", +// Location(39.9, 116.3), +// District("华鼎世家对面") +// ) + + println(talk.speaker !== copiedTalk.speaker) + println(talk.speaker.company !== copiedTalk.speaker.company) + println(talk.speaker.company.location === copiedTalk.speaker.company.location) +} + +data class District(var name: String) + +data class Location(var lat: Double, var lng: Double) + +data class Company(var name: String, var location: Location, var district: District): DeepCopyable + +data class Speaker(var name: String, var age: Int, var company: Company): DeepCopyable + +data class Talk(var name: String, var speaker: Speaker): DeepCopyable + + +inline class Span(val value: Long) +value class Duration(val value: Long) \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/deepcopy/TestDeepCopy.kt b/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/deepcopy/TestDeepCopy.kt new file mode 100644 index 0000000..153db4b --- /dev/null +++ b/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/deepcopy/TestDeepCopy.kt @@ -0,0 +1,22 @@ +package com.bennyhuo.kotlin.js.deepcopy + +/** + * Created by benny. + */ +interface DeepCopyable + +fun T.deepCopy(): T { + val constructor = this::class.js.asDynamic() + val newInstance = js("{}") + newInstance.__proto__ = constructor.prototype + val parameters = (1..Int.MAX_VALUE).takeWhile { + constructor.prototype["component$it"] !== undefined + }.map { + constructor.prototype["component$it"].call(this).unsafeCast() + .let { + (it as? DeepCopyable)?.deepCopy() ?: it + } + }.toTypedArray() + constructor.apply(newInstance, parameters) + return newInstance as T +} \ No newline at end of file diff --git a/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/kclassvalue/KClassIssue.kt b/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/kclassvalue/KClassIssue.kt new file mode 100644 index 0000000..f84567e --- /dev/null +++ b/code/Kotlin-Sample/kotlin-js-sample/src/main/kotlin/com/bennyhuo/kotlin/js/kclassvalue/KClassIssue.kt @@ -0,0 +1,17 @@ +package com.bennyhuo.kotlin.js.kclassvalue + +/** + * Created by benny. + */ +fun testKClass() { + val anyClass = Any::class + val anyClass2 = Any::class + + println(anyClass === anyClass2) + + val personClass = Person::class + val personClass2 = Person::class + println(personClass === personClass2) +} + +class Person \ No newline at end of file diff --git a/code/Kotlin-Sample/opt-in-sample/build.gradle.kts b/code/Kotlin-Sample/opt-in-sample/build.gradle.kts new file mode 100644 index 0000000..1642f91 --- /dev/null +++ b/code/Kotlin-Sample/opt-in-sample/build.gradle.kts @@ -0,0 +1,27 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + java + kotlin("jvm") +} + +group = "com.bennyhuo" +version = "1.0-SNAPSHOT" + +repositories { + maven("https://mirrors.tencent.com/nexus/repository/maven-public/") +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0") +} + +tasks.getByName("compileKotlin") { + kotlinOptions.freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn") +} + +tasks.getByName("test") { + useJUnitPlatform() +} \ No newline at end of file diff --git a/code/Kotlin-Sample/opt-in-sample/src/main/java/com/bennyhuo/kotlin/optinsample/Annotations.kt b/code/Kotlin-Sample/opt-in-sample/src/main/java/com/bennyhuo/kotlin/optinsample/Annotations.kt new file mode 100644 index 0000000..9a02a36 --- /dev/null +++ b/code/Kotlin-Sample/opt-in-sample/src/main/java/com/bennyhuo/kotlin/optinsample/Annotations.kt @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.optinsample + +@RequiresOptIn("This api is not stable!!", RequiresOptIn.Level.WARNING) +annotation class UnstableApi + +@RequiresOptIn("This api is removed.", RequiresOptIn.Level.ERROR) +annotation class UnsupportedApi diff --git a/code/Kotlin-Sample/opt-in-sample/src/main/java/com/bennyhuo/kotlin/optinsample/SampleApi.kt b/code/Kotlin-Sample/opt-in-sample/src/main/java/com/bennyhuo/kotlin/optinsample/SampleApi.kt new file mode 100644 index 0000000..81b3e8a --- /dev/null +++ b/code/Kotlin-Sample/opt-in-sample/src/main/java/com/bennyhuo/kotlin/optinsample/SampleApi.kt @@ -0,0 +1,33 @@ +package com.bennyhuo.kotlin.optinsample + +class SampleApi { + + fun stableAndFreeToUse() { + + } + + @UnstableApi + fun unstableAndPayAttention() { + + } + + @Deprecated( + message = "Use stableAndFreeToUse instead.", + ReplaceWith("stableAndFreeToUse()") + ) + @UnsupportedApi + fun removedApiDontUse(): Unit = error("removed.") + + fun newApiForDeprecated(key: String, value: String) { + + } + + @Deprecated( + message = "Use newApiForDeprecated instead.", + replaceWith = ReplaceWith("newApiForDeprecated(key, value)") + ) + fun deprecatedDontUse(key: String, value: String) { + + } + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/settings.gradle.kts b/code/Kotlin-Sample/settings.gradle.kts new file mode 100644 index 0000000..5dc3e5e --- /dev/null +++ b/code/Kotlin-Sample/settings.gradle.kts @@ -0,0 +1,7 @@ +rootProject.name = "Kotlin-Sample" + +include(":opt-in-sample",":deprecated-sample") +include(":kotlin-android-sample") +include("kotlin-js-sample") +include("kclass-issue") +include("Kotlin-mpp-sample") diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/api/UpdateApi.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/api/UpdateApi.kt new file mode 100644 index 0000000..9b2d767 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/api/UpdateApi.kt @@ -0,0 +1,41 @@ +package com.bennyhuo.kotlin.api + +import io.reactivex.rxjava3.core.Observable +import okhttp3.Dispatcher +import okhttp3.OkHttpClient +import retrofit2.Call +import retrofit2.Retrofit +import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.http.GET +import java.util.concurrent.Executors + +data class Config(val bannerId: String, val bannerUrl: String) + +interface UpdateApi { + + @GET("/") + suspend fun getConfigSuspend(): List + + @GET("/") + fun getConfig(): Call> + + @GET("/") + fun getConfigObservable(): Observable> +} + +val updateApi by lazy { + Retrofit.Builder() + .client( + OkHttpClient.Builder() + .dispatcher(Dispatcher(Executors.newFixedThreadPool(3) { + Thread(it).also { it.isDaemon = true } + })) + .build() + ) + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl("http://localhost:8080") + .build() + .create(UpdateApi::class.java) +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/BackTicks.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/BackTicks.kt new file mode 100644 index 0000000..726dc71 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/BackTicks.kt @@ -0,0 +1,31 @@ +package com.bennyhuo.kotlin.basics + +import kotlinx.datetime.toInstant + +/** + * Created by benny. + */ +fun main() { + val result = 2 `**` 3 + println(result) + val history = History("2016-02-19T00:00:00.000Z".toInstant().toEpochMilliseconds(), "Kotlin 1.0 release!") + println(history.`when`()) +} + +fun `fun`() { + +} + +@JvmName("classInJava") +fun `class`() { + +} + +@JvmName("This_is_a_test") +fun `This is a test`() { + +} + +infix fun Number.`**`(power: Number): Double { + return Math.pow(this.toDouble(), power.toDouble()) +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/FunctionType.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/FunctionType.kt new file mode 100644 index 0000000..ce2008f --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/FunctionType.kt @@ -0,0 +1,70 @@ +package com.bennyhuo.kotlin.coroutines + +import kotlinx.coroutines.runBlocking + +/** + * Created by benny. + */ +fun a0() { + +} + +suspend fun a1() { + +} + +fun b0(): Int { + TODO() +} + +suspend fun b1(): Int { + TODO() +} + +fun Int.c0(block: (Int) -> String): String { + TODO() +} + +fun c00(i: Int, block: (Int) -> String): String { + TODO() +} + +suspend fun Int.c1(block: (Int) -> String): String { + TODO() +} + +suspend fun c11(i: Int, block: (Int) -> String): String { + TODO() +} + +fun x(block: suspend Int.((Int) -> String) -> String) { + runBlocking { + block(1) { + it.toString() + } + } +} + +fun Int.println() { + +} + +fun main() { + val typeA0 = ::a0 // () -> Unit + val typeA1 = ::a1 // suspend () -> Unit + + val typeB0 = ::b0 // () -> Int + val typeB1 = ::b1 // suspend () -> Int + + val typeC0 = Int::c0 // Int.((Int) -> String) -> String + val typeC0x = 1::c0 // ((Int) -> String) -> String + val typeC00 = ::c00 // (Int, (Int) -> String) -> String + val typeC1 = Int::c1 // suspend Int.((Int) -> String) -> String + val typeC11 = ::c11 // suspend (Int, (Int) -> String) -> String + + x(typeC1) + x(typeC11) + + listOf(1,2,3).forEach(Int::println) + listOf(1,2,3).forEach(::println) +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/History.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/History.java new file mode 100644 index 0000000..3a53ffe --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/History.java @@ -0,0 +1,23 @@ +package com.bennyhuo.kotlin.basics; + +/** + * Created by benny. + */ +public class History { + + private long when; + private String eventName; + + public History(long when, String eventName) { + this.when = when; + this.eventName = eventName; + } + + public long when() { + return when; + } + + public String eventName() { + return eventName; + } +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/Main.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/Main.java new file mode 100644 index 0000000..adf1298 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/basics/Main.java @@ -0,0 +1,12 @@ +package com.bennyhuo.kotlin.basics; + +/** + * Created by benny. + */ +public class Main { + public static void main(String[] args) { + BackTicksKt.fun(); + BackTicksKt.classInJava(); + BackTicksKt.This_is_a_test(); + } +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/CallbackToCoroutines.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/CallbackToCoroutines.kt new file mode 100644 index 0000000..a695cb4 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/CallbackToCoroutines.kt @@ -0,0 +1,212 @@ +package com.bennyhuo.kotlin.coroutines + +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.conflate +import kotlin.concurrent.thread +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException +import kotlin.coroutines.suspendCoroutine + +suspend fun main() { + println(runTaskSuspend()) + + try { + println(sendRequestSuspend()) + } catch (e: Exception) { + println("send request: $e") + } + + val scope = CoroutineScope(Dispatchers.Default) + scope.launch { + try { + println(sendRequestCancellableSuspend()) + } catch (e: Exception) { + println("send request cancellable: $e") + } + }.join() + + scope.launch { + startTaskAsFlow().collect { + when(it) { + OnComplete -> println("Done") + is OnError -> println("Error: ${it.t}") + is OnProgress -> println("Progress: ${it.value}") + is OnResult<*> -> println("Result: ${it.value}") + } + } + }.join() + +// delay(100) +// scope.cancel() +} + +//region single method +/** + * Delayed task, like handler.post + */ +fun interface SingleMethodCallback { + fun onCallback(value: String) +} + +fun runTask(callback: SingleMethodCallback) { + thread { + Thread.sleep(100) + callback.onCallback("runTask result") + } +} + +//region suspend +suspend fun runTaskSuspend() = suspendCoroutine { continuation -> + runTask { + continuation.resume(it) + } +} +//endregion +//endregion + +//region success or failure +/** + * Http request callback + * Dialog yes/no + */ +interface SuccessOrFailureCallback { + fun onSuccess(value: String) + + fun onError(t: Throwable) +} + +fun sendRequest(callback: SuccessOrFailureCallback) { + thread { + try { + Thread.sleep(100) + callback.onSuccess("Success") + } catch (e: Exception) { + callback.onError(e) + } + } +} + +//region suspend +suspend fun sendRequestSuspend() = suspendCoroutine { + continuation -> + sendRequest(object: SuccessOrFailureCallback { + override fun onSuccess(value: String) { + continuation.resume(value) + } + + override fun onError(t: Throwable) { + continuation.resumeWithException(t) + } + }) +} +//endregion + +fun interface Cancellable { + fun cancel() +} + +fun sendRequestCancellable(callback: SuccessOrFailureCallback):Cancellable { + val t = thread { + try { + Thread.sleep(1000) + callback.onSuccess("Success") + } catch (e: Exception) { + callback.onError(e) + } + } + return Cancellable { + t.interrupt() + } +} + +//region cancellable suspend +suspend fun sendRequestCancellableSuspend() = suspendCancellableCoroutine { + continuation -> + val cancellable = sendRequestCancellable(object: SuccessOrFailureCallback { + override fun onSuccess(value: String) { + continuation.resume(value) + } + + override fun onError(t: Throwable) { + continuation.resumeWithException(t) + } + }) + continuation.invokeOnCancellation { + cancellable.cancel() + } +} +//endregion +//endregion + +//region multi path +/** + * Download task callback + */ +interface MultiPathsCallback { + + fun onProgress(value: Int) + + fun onResult(value: T) + + fun onError(t: Throwable) + + fun onComplete() + +} + +fun startTask(callback: MultiPathsCallback): Cancellable { + val t = thread { + try { + (0..100).forEach { + Thread.sleep(10) + callback.onProgress(it) + } + callback.onResult("Done") + callback.onComplete() + } catch (e: Exception) { + callback.onError(e) + } + } + return Cancellable { + t.interrupt() + } +} + +//region suspend +sealed interface Event +class OnProgress(val value: Int): Event +class OnError(val t: Throwable): Event +class OnResult(val value: T): Event +object OnComplete: Event + +fun startTaskAsFlow() = callbackFlow { + val cancellable = startTask(object: MultiPathsCallback { + override fun onProgress(value: Int) { + trySendBlocking(OnProgress(value)) + } + + override fun onResult(value: String) { + trySendBlocking(OnResult(value)) + } + + override fun onError(t: Throwable) { + trySendBlocking(OnError(t)) + } + + override fun onComplete() { + trySendBlocking(OnComplete) + close() + } + }) + + + awaitClose { + cancellable.cancel() + } +}.conflate() +//endregion +//endregion \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/HowSuspendFunctionWork.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/HowSuspendFunctionWork.kt new file mode 100644 index 0000000..ee10d3d --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/HowSuspendFunctionWork.kt @@ -0,0 +1,110 @@ +package com.bennyhuo.kotlin.coroutines + +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import java.util.concurrent.Executors +import kotlin.concurrent.thread +import kotlin.coroutines.Continuation +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine +import kotlin.reflect.KMutableProperty0 + +/** + * Created by benny. + */ +suspend fun main() { + eatGame() +} + +suspend fun noSuspend() { + println("noSuspend called.") +} + +suspend fun suspended() { + delay(100) + println("resumed after 100ms") +} + +suspend fun fakeSuspend() = suspendCoroutine { + it.resume(1) +} + +suspend fun fakeSuspend2() = suspendCoroutine { + Thread.sleep(100) + it.resume(1) +} + +suspend fun realSuspend() = suspendCoroutine { + thread { + Thread.sleep(100) + it.resume(1) + } +} + +class EatGame { + private var feedContinuation: Continuation? = null + private var eatContinuation: Continuation? = null + private var eatAttempts = 0 + + var isActive: Boolean = true + private set + + suspend fun eat(): String { + return if (isActive) suspendCoroutine { + this.eatContinuation = it + resumeContinuation(this::feedContinuation, eatAttempts++) + } else "" + } + + suspend fun feed(food: String): Int { + return if (isActive) suspendCoroutine { + this.feedContinuation = it + resumeContinuation(this::eatContinuation, food) + } else -1 + } + + fun timeout() { + isActive = false + resumeContinuation(this::feedContinuation, eatAttempts) + resumeContinuation(this::eatContinuation, "") + } + + private fun resumeContinuation( + continuationRef: KMutableProperty0?>, + value: T + ) { + val continuation = continuationRef.get() + continuationRef.set(null) + continuation?.resume(value) + } +} + +suspend fun eatGame() { + coroutineScope { + val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + val game = EatGame() + launch(dispatcher) { + println("Ready Go!") + delay(1000) + game.timeout() + println("Timeout!") + } + launch(dispatcher) { + while (game.isActive) { + delay(60) + val food = Math.random() + println("[${Thread.currentThread().name} #1] Feed $food >>>") + println("[${Thread.currentThread().name} #1] Complete: ${game.feed("$food")}") + } + } + + launch(dispatcher) { + while (game.isActive) { + delay(50) + println("[${Thread.currentThread().name} #2] Eat ${game.eat()} <<<") + } + } + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/Interceptors.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/Interceptors.kt new file mode 100644 index 0000000..be8af23 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/Interceptors.kt @@ -0,0 +1,75 @@ +package com.bennyhuo.kotlin.coroutines + +import kotlinx.coroutines.* +import kotlin.concurrent.thread +import kotlin.coroutines.Continuation +import kotlin.coroutines.ContinuationInterceptor +import kotlin.coroutines.CoroutineContext + +/** + * Created by benny. + */ +suspend fun main() { + + log(1) + + val job = GlobalScope.launch( + context = CoroutineName("Hello") + MyNewContinuationInterceptor2() + MyNewContinuationInterceptor1(), + start = CoroutineStart.UNDISPATCHED + ) { + log(2) + delay(1000) + log(3) + log(coroutineContext[ContinuationInterceptor]) + } + + log(4) + + job.join() + + log(5) +} + +private class MyNewContinuationInterceptor1 : ContinuationInterceptor { + + companion object Key : CoroutineContext.Key + + override val key: CoroutineContext.Key<*> = MyNewContinuationInterceptor1 + + override fun interceptContinuation(continuation: Continuation): Continuation { + return object : Continuation { + override val context: CoroutineContext = continuation.context + + override fun resumeWith(result: Result) { + log(" $result") + thread(name = "MyMain1") { + continuation.resumeWith(result) + } + } + } + } +} + +private class MyNewContinuationInterceptor2 : ContinuationInterceptor { + + companion object Key : CoroutineContext.Key + + override val key: CoroutineContext.Key<*> = MyNewContinuationInterceptor2 + + override fun interceptContinuation(continuation: Continuation): Continuation { + return object : Continuation { + override val context: CoroutineContext = continuation.context + + override fun resumeWith(result: Result) { + log(" $result") + thread(name = "MyMain2") { + continuation.resumeWith(result) + } + } + } + } +} + +fun log(message: Any?) { + println("[${Thread.currentThread().name}] $message") +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/JavaMain.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/JavaMain.java new file mode 100644 index 0000000..d74b456 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/JavaMain.java @@ -0,0 +1,38 @@ +package com.bennyhuo.kotlin.coroutines; + +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.CompletableFuture; + +import kotlin.coroutines.Continuation; +import kotlin.coroutines.CoroutineContext; +import kotlin.coroutines.EmptyCoroutineContext; +import kotlin.coroutines.intrinsics.IntrinsicsKt; + +public class JavaMain { + public static void main(String[] args) { + CompletableFuture future = new CompletableFuture<>(); + Object result = SuspendToBlockingKt.suspendableApi(new Continuation() { + @NotNull + @Override + public CoroutineContext getContext() { + return EmptyCoroutineContext.INSTANCE; + } + + @Override + public void resumeWith(@NotNull Object o) { + if(o instanceof String) { + future.complete((String) o); + } else { + future.completeExceptionally((Throwable) o); + } + } + }); + + if (result != IntrinsicsKt.getCOROUTINE_SUSPENDED()) { + future.complete((String) result); + } + + System.out.println(future.join()); + } +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/SuspendToBlocking.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/SuspendToBlocking.kt new file mode 100644 index 0000000..130eb62 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutines/SuspendToBlocking.kt @@ -0,0 +1,34 @@ +package com.bennyhuo.kotlin.coroutines + +import kotlinx.coroutines.* +import kotlinx.coroutines.future.future +import kotlin.coroutines.EmptyCoroutineContext + +suspend fun suspendableApi(): String { + if(Math.random() > 0.5) delay(1000) + + return "bilibli 关注我:bennyhuo 不是算命的" +} + +fun futureMain() { + val scope = CoroutineScope(Dispatchers.IO) + + scope.future { + suspendableApi() + }.join() + .let(::println) +} + +fun main() { + val value = runBlocking { + suspendableApi() + } + println(value) + + futureMain() +} + +//suspend fun main() { +// val value = suspendableApi() +// println(value) +//} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/DelicateGlobalScope.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/DelicateGlobalScope.kt new file mode 100644 index 0000000..d777222 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/DelicateGlobalScope.kt @@ -0,0 +1,19 @@ +package com.bennyhuo.kotlin.coroutinesupdate + +import kotlinx.coroutines.* + +@OptIn(DelicateCoroutinesApi::class) +suspend fun main() { + val jobInGlobal = GlobalScope.launch() { + println("扶我起来!我还能再战两年!") + }.join() + GlobalScope.cancel() + + val scope = CoroutineScope(Dispatchers.IO) + val job = scope.launch { + + } + + job.cancel() + scope.cancel() +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/FlowUpdates.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/FlowUpdates.kt new file mode 100644 index 0000000..b5be589 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/FlowUpdates.kt @@ -0,0 +1,129 @@ +package com.bennyhuo.kotlin.coroutinesupdate + +import android.os.Handler +import android.os.HandlerThread +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.flow +import java.util.concurrent.CopyOnWriteArrayList +import kotlin.concurrent.thread + +suspend fun main() { + flowSamples() +} + +suspend fun flowSamples() { + flow { + emit(1) + emit(2) + }.collect { + println(it) + } + + channelFlow { + send(1) + withContext(Dispatchers.IO) { + send(2) + } + + thread { + trySendBlocking(3) + }.join() + }.collect { + println(it) + } + + callbackFlow { + send(1) + withContext(Dispatchers.IO) { + send(2) + } + + awaitClose { + // nothing to do. + println("closed") + } + }.collect { + println(it) + } +} + +suspend fun callbackFlowSample() { + val application = Application() + application.start() + + + val eventFlow = callbackFlow { + val callback = Application.Callback { + trySendBlocking(it) + } + application.registerCallback(callback) + + awaitClose { + application.unregisterCallback(callback) + } + } + + val scope = CoroutineScope(Dispatchers.IO) + scope.launch { + eventFlow.collect { + println(it) + } + } + + delay(5000) + scope.cancel() + + delay(10_000) + application.stop() +} + + +class Application { + + fun interface Callback { + fun onCallBack(value: Int) + } + + private val handlerThread = HandlerThread("App") + + private val handler by lazy { + handlerThread.start() + Handler(handlerThread.looper) + } + + private val callbacks = CopyOnWriteArrayList() + + fun registerCallback(callback: Callback) { + this.callbacks += callback + } + + fun unregisterCallback(callback: Callback) { + this.callbacks -= callback + } + + fun start() { + runApp() + } + + fun stop() { + handlerThread.quit() + } + + private var eventId = 0 + + private fun runApp() { + this.callbacks.forEach { + it.onCallBack(eventId) + } + + eventId++ + handler.postDelayed(::runApp, 1000) + } + +} + diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/NewChannelApis.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/NewChannelApis.kt new file mode 100644 index 0000000..c145b72 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/NewChannelApis.kt @@ -0,0 +1,56 @@ +package com.bennyhuo.kotlin.coroutinesupdate + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.channels.* +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.selects.select +import kotlinx.coroutines.withContext + +suspend fun main() { + val channel = Channel() +// channel.trySend(1).isSuccess // offer +// channel.tryReceive().getOrNull() // poll +// +// channel.trySendBlocking(1) // sendBlocking + + withContext(Dispatchers.Default) { + val producer = launch { + (0 .. 5).forEach { + channel.send(it) + } + channel.close() + } + + val consumer = launch { + while (isActive && !channel.isClosedForReceive) { + select { + channel.onReceiveCatching { + println("$it - ${it.isClosed}") + } + } + + // or + // val value = channel.onReceiveCatching() + } + } + + select { + consumer.onJoin + } + + + val consumer1 = produce { + + } + + val producer1 = actor { + + } + + + BroadcastChannel(1) + ConflatedBroadcastChannel() + + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/widgets/Button.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/widgets/Button.kt new file mode 100644 index 0000000..ed732f3 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/coroutinesupdate/widgets/Button.kt @@ -0,0 +1,22 @@ +package com.bennyhuo.kotlin.coroutinesupdate.widgets + +fun interface OnClickListener { + fun onClick(view: View) +} + +open class View { + + private var onClickListener: OnClickListener? = null + + fun setOnClickListener(onClickListener: OnClickListener) { + this.onClickListener = onClickListener + } + + fun click() { + onClickListener?.onClick(this) + } +} + +class Button: View() { + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/deprecated/DeprecatedSample.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/deprecated/DeprecatedSample.kt new file mode 100644 index 0000000..4005d20 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/deprecated/DeprecatedSample.kt @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.deprecated + +import com.bennyhuo.kotlin.deprecatedsample.Api + +fun main() { + Api.deprecatedDontUse("name", "bennyhuo 不是算命的") +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/Main.kt new file mode 100644 index 0000000..6cb0cf1 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/Main.kt @@ -0,0 +1,22 @@ +package com.bennyhuo.kotlin.ide + +interface Api { + val state: Int + + fun start() + + fun stop() +} + +class ApiImpl : Api { + override val state: Int + get() = 0 + + override fun start() { + } + + override fun stop() { + } + + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/Sample.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/Sample.kt new file mode 100644 index 0000000..f7fff2b --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/Sample.kt @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.ide + +/** + * Created by benny at 2021/6/16 21:58. + */ +class Sample { +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/SampleJava.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/SampleJava.java new file mode 100644 index 0000000..bb14bbd --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/ide/SampleJava.java @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.ide; + +/** + * Created by benny at 2021/6/16 21:59. + */ +public class SampleJava { +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/measuretime/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/measuretime/Main.kt new file mode 100644 index 0000000..58cf7e9 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/measuretime/Main.kt @@ -0,0 +1,66 @@ +package com.bennyhuo.kotlin.measuretime + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlin.concurrent.fixedRateTimer +import kotlin.time.* + + +inline fun timeCost(block: ()-> Unit): Long { + val startTime = System.currentTimeMillis() + block() + return System.currentTimeMillis() - startTime +} + +inline fun timeCostReturns(block: () -> T): Pair { + val startTime = System.currentTimeMillis() + val result = block() + return result to (System.currentTimeMillis() - startTime) +} + +@OptIn(ExperimentalTime::class) +suspend fun main() { + + val duration = measureTime { + Thread.sleep(100) + } + println(duration) + + val timeCost = timeCost { + Thread.sleep(100) + } + println(timeCost) + +// val (value, duration2) = measureTimedValue { +// Thread.sleep(500) +// +// 1000 +// } + + val (value, duration2) = timeCostReturns { + Thread.sleep(500) + + 1000 + } + + println(value) + println(duration2) + + val scope = CoroutineScope(Dispatchers.IO) + scope.launch { + + val duration = measureTime { + delay(1000) + } + println(duration) + + val mark = TimeSource.Monotonic.markNow() + delay(1000) + println(mark.elapsedNow()) + }.join() + + + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/nonfinalfunction/Base.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/nonfinalfunction/Base.kt new file mode 100644 index 0000000..4860aa5 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/nonfinalfunction/Base.kt @@ -0,0 +1,45 @@ +package com.bennyhuo.kotlin.nonfinalfunction + +import kotlin.random.Random + +/** + * Created by benny. + */ +open class Base { + + open val name = "Base" + + val id = generateId() + + init { + println("Base: id: $id, name: ${xyz()}") + } + + open fun generateId(): Int { + return Random(System.currentTimeMillis()).nextInt(10000000) + } + + fun xyz(): String { + generateId() + return this.name + } + +} + +class Derived: Base() { + + override val name = "Derived" + + init { + println("Derived: id: $id, name: $name") + } + + override fun generateId(): Int { + return 1 + } + +} + +fun main() { + val d = Derived() +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/optin/OptInSample.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/optin/OptInSample.kt new file mode 100644 index 0000000..a6df165 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/optin/OptInSample.kt @@ -0,0 +1,19 @@ +package com.bennyhuo.kotlin.optin + +import com.bennyhuo.kotlin.optinsample.SampleApi +import com.bennyhuo.kotlin.optinsample.UnsupportedApi + + +@UnsupportedApi +fun main() { + val sampleApi = SampleApi() + sampleApi.stableAndFreeToUse() + sampleApi.unstableAndPayAttention() + sampleApi.removedApiDontUse() + sampleApi.newApiForDeprecated("a", "b") +} + +@UnsupportedApi +fun main2() { + main() +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/CurryingSample.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/CurryingSample.kt new file mode 100644 index 0000000..d4df742 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/CurryingSample.kt @@ -0,0 +1,22 @@ +package com.bennyhuo.kotlin.other.currying + +import cn.tursom.core.curry.currying + +/** + * Created by benny. + */ + +enum class LoggerLevel { + DEBUG, + INFO, + WARN, + ERROR +} + +fun log(context: Any?, level: LoggerLevel, message: Any?) { + println("$level - [$context]: $message") +} + +fun main() { + ::log.currying()(1234)(LoggerLevel.DEBUG)("Hello Curried from Kotlin !!!!!!!!!!") +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/currying.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/currying.kt new file mode 100644 index 0000000..a5f0b5c --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/currying.kt @@ -0,0 +1,230 @@ +package cn.tursom.core.curry + +operator fun ((T1, T2) -> R).invoke() = this +operator fun ((T1, T2) -> R).invoke(a1: T1) = { a2: T2 -> this(a1, a2) } + +operator fun ((T1, T2, T3) -> R).invoke() = this +operator fun ((T1, T2, T3) -> R).invoke(a1: T1) = { a2: T2, a3: T3 -> this(a1, a2, a3) } +operator fun ((T1, T2, T3) -> R).invoke(a1: T1, a2: T2) = { a3: T3 -> this(a1, a2, a3) } + +operator fun ((T1, T2, T3, T4) -> R).invoke() = this +operator fun ((T1, T2, T3, T4) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4 -> this(a1, a2, a3, a4) } +operator fun ((T1, T2, T3, T4) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4 -> this(a1, a2, a3, a4) } +operator fun ((T1, T2, T3, T4) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4 -> this(a1, a2, a3, a4) } + +operator fun ((T1, T2, T3, T4, T5) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5 -> this(a1, a2, a3, a4, a5) } +operator fun ((T1, T2, T3, T4, T5) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5 -> this(a1, a2, a3, a4, a5) } +operator fun ((T1, T2, T3, T4, T5) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5 -> this(a1, a2, a3, a4, a5) } +operator fun ((T1, T2, T3, T4, T5) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5 -> this(a1, a2, a3, a4, a5) } + +operator fun ((T1, T2, T3, T4, T5, T6) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6 -> this(a1, a2, a3, a4, a5, a6) } +operator fun ((T1, T2, T3, T4, T5, T6) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6 -> this(a1, a2, a3, a4, a5, a6) } +operator fun ((T1, T2, T3, T4, T5, T6) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6 -> this(a1, a2, a3, a4, a5, a6) } +operator fun ((T1, T2, T3, T4, T5, T6) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6 -> this(a1, a2, a3, a4, a5, a6) } +operator fun ((T1, T2, T3, T4, T5, T6) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6 -> this(a1, a2, a3, a4, a5, a6) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7 -> this(a1, a2, a3, a4, a5, a6, a7) } +operator fun ((T1, T2, T3, T4, T5, T6, T7) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7 -> this(a1, a2, a3, a4, a5, a6, a7) } +operator fun ((T1, T2, T3, T4, T5, T6, T7) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7 -> this(a1, a2, a3, a4, a5, a6, a7) } +operator fun ((T1, T2, T3, T4, T5, T6, T7) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7 -> this(a1, a2, a3, a4, a5, a6, a7) } +operator fun ((T1, T2, T3, T4, T5, T6, T7) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7 -> this(a1, a2, a3, a4, a5, a6, a7) } +operator fun ((T1, T2, T3, T4, T5, T6, T7) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7 -> this(a1, a2, a3, a4, a5, a6, a7) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13, a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = { a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13, a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = { a14: T14, a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14) = { a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13, a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = { a14: T14, a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14) = { a15: T15, a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15) = { a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13, a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = { a14: T14, a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14) = { a15: T15, a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15) = { a16: T16, a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16) = { a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = { a14: T14, a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14) = { a15: T15, a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15) = { a16: T16, a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16) = { a17: T17, a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17) = { a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = { a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14) = { a15: T15, a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15) = { a16: T16, a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16) = { a17: T17, a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17) = { a18: T18, a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18) = { a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } + +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke() = this +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1) = { a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2) = { a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3) = { a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = { a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = { a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = { a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = { a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = { a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = { a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = { a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = { a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = { a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = { a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14) = { a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15) = { a16: T16, a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16) = { a17: T17, a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17) = { a18: T18, a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18) = { a19: T19, a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } +operator fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19) = { a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } + diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/curyingMethod.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/curyingMethod.kt new file mode 100644 index 0000000..cec1ffa --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/curyingMethod.kt @@ -0,0 +1,21 @@ +package cn.tursom.core.curry + +fun ((T1, T2) -> R).currying() = { a1: T1 -> { a2: T2 -> this(a1, a2) } } +fun ((T1, T2, T3) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> this(a1, a2, a3) } } } +fun ((T1, T2, T3, T4) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> this(a1, a2, a3, a4) } } } } +fun ((T1, T2, T3, T4, T5) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> this(a1, a2, a3, a4, a5) } } } } } +fun ((T1, T2, T3, T4, T5, T6) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> this(a1, a2, a3, a4, a5, a6) } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> this(a1, a2, a3, a4, a5, a6, a7) } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> this(a1, a2, a3, a4, a5, a6, a7, a8) } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9) } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> { a14: T14 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } } } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> { a14: T14 -> { a15: T15 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } } } } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> { a14: T14 -> { a15: T15 -> { a16: T16 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } } } } } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> { a14: T14 -> { a15: T15 -> { a16: T16 -> { a17: T17 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } } } } } } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> { a14: T14 -> { a15: T15 -> { a16: T16 -> { a17: T17 -> { a18: T18 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } } } } } } } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> { a14: T14 -> { a15: T15 -> { a16: T16 -> { a17: T17 -> { a18: T18 -> { a19: T19 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } } } } } } } } } } } } } } } } } } } +fun ((T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) -> R).currying() = { a1: T1 -> { a2: T2 -> { a3: T3 -> { a4: T4 -> { a5: T5 -> { a6: T6 -> { a7: T7 -> { a8: T8 -> { a9: T9 -> { a10: T10 -> { a11: T11 -> { a12: T12 -> { a13: T13 -> { a14: T14 -> { a15: T15 -> { a16: T16 -> { a17: T17 -> { a18: T18 -> { a19: T19 -> { a20: T20 -> this(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } } } } } } } } } } } } } } } } } } } } diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/uncurrying.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/uncurrying.kt new file mode 100644 index 0000000..54b8fc4 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/other/currying/tursomcurrying/uncurrying.kt @@ -0,0 +1,21 @@ +package cn.tursom.core.curry + +operator fun ((T1) -> (T2) -> R).invoke(a1: T1, a2: T2) = this(a1)(a2) +operator fun ((T1) -> (T2) -> (T3) -> R).invoke(a1: T1, a2: T2, a3: T3) = this(a1)(a2)(a3) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4) = this(a1)(a2)(a3)(a4) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5) = this(a1)(a2)(a3)(a4)(a5) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6) = this(a1)(a2)(a3)(a4)(a5)(a6) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> (T14) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> (T14) -> (T15) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> (T14) -> (T15) -> (T16) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> (T14) -> (T15) -> (T16) -> (T17) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> (T14) -> (T15) -> (T16) -> (T17) -> (T18) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> (T14) -> (T15) -> (T16) -> (T17) -> (T18) -> (T19) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18)(a19) +operator fun ((T1) -> (T2) -> (T3) -> (T4) -> (T5) -> (T6) -> (T7) -> (T8) -> (T9) -> (T10) -> (T11) -> (T12) -> (T13) -> (T14) -> (T15) -> (T16) -> (T17) -> (T18) -> (T19) -> (T20) -> R).invoke(a1: T1, a2: T2, a3: T3, a4: T4, a5: T5, a6: T6, a7: T7, a8: T8, a9: T9, a10: T10, a11: T11, a12: T12, a13: T13, a14: T14, a15: T15, a16: T16, a17: T17, a18: T18, a19: T19, a20: T20) = this(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18)(a19)(a20) diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/Java8Sam.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/Java8Sam.java new file mode 100644 index 0000000..f4dda4f --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/Java8Sam.java @@ -0,0 +1,17 @@ +package com.bennyhuo.kotlin.samissue; + +public class Java8Sam { + public static void main(String[] args) { + View view = new View(); + view.setOnSizeChangedListener((width, height) -> { + System.out.println("w: " + width + ", h: " + height); + }); + + view.setOnSizeChangedListener(new View.OnSizeChangedListener() { + @Override + public void onSizeChanged(int width, int height) { + System.out.println("w: " + width + ", h: " + height); + } + }); + } +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/KotlinSam.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/KotlinSam.kt new file mode 100644 index 0000000..5cd2de1 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/KotlinSam.kt @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.samissue + +fun main() { + View().setOnSizeChangedListener { width, height -> + println("w: $width, h: $height") + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/View.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/View.java new file mode 100644 index 0000000..a0f38de --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/View.java @@ -0,0 +1,12 @@ +package com.bennyhuo.kotlin.samissue; + +public class View { + // Single Abstract method + public interface OnSizeChangedListener { + void onSizeChanged(int width, int height); + } + + public void setOnSizeChangedListener(OnSizeChangedListener onSizeChangedListener) { + + } +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/sub/Java8Sam.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/sub/Java8Sam.java new file mode 100644 index 0000000..5f5d172 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/sub/Java8Sam.java @@ -0,0 +1,19 @@ +package com.bennyhuo.kotlin.samissue.sub; + +import com.bennyhuo.kotlin.samissue.View; + +public class Java8Sam { + public static void main(String[] args) { + View view = new View(); + view.setOnSizeChangedListener((width, height) -> { + System.out.println("w: " + width + ", h: " + height); + }); + + view.setOnSizeChangedListener(new View.OnSizeChangedListener() { + @Override + public void onSizeChanged(int width, int height) { + System.out.println("w: " + width + ", h: " + height); + } + }); + } +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/sub/SubSam.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/sub/SubSam.kt new file mode 100644 index 0000000..13c1811 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/samissue/sub/SubSam.kt @@ -0,0 +1,10 @@ +package com.bennyhuo.kotlin.samissue.sub + +import com.bennyhuo.kotlin.samissue.View + +fun main() { + View().setOnSizeChangedListener { width, height -> + println("w: $width, h: $height") + } + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/CoroutineUpdateTask.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/CoroutineUpdateTask.kt new file mode 100644 index 0000000..26c07a2 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/CoroutineUpdateTask.kt @@ -0,0 +1,32 @@ +package com.bennyhuo.kotlin.scheduledtask + +import com.bennyhuo.kotlin.api.updateApi +import kotlinx.coroutines.* + +class CoroutineUpdateTask : UpdateTask { + + private var scope: CoroutineScope? = null + + override fun scheduleUpdate(interval: Long) { + cancel() + val scope = CoroutineScope(Dispatchers.IO) + scope.launch { + while (isActive) { + try { + updateApi.getConfigSuspend().let(::println) + } catch (e: Exception) { + e.printStackTrace() + if (e is CancellationException) throw e + } + delay(interval) + } + } + + this.scope = scope + } + + override fun cancel() { + scope?.cancel() + scope = null + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/HandlerUpdateTask.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/HandlerUpdateTask.kt new file mode 100644 index 0000000..3ae482a --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/HandlerUpdateTask.kt @@ -0,0 +1,55 @@ +package com.bennyhuo.kotlin.scheduledtask + +import android.os.Handler +import android.os.HandlerThread +import android.os.Message +import com.bennyhuo.kotlin.api.Config +import com.bennyhuo.kotlin.api.updateApi +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class HandlerUpdateTask : UpdateTask { + + private var handlerThread: HandlerThread? = null + private var handler: Handler? = null + + private fun Handler.triggerUpdateNext(delay: Long) { + val message = Message.obtain(handler) { + updateApi.getConfig().enqueue(object : Callback> { + override fun onResponse( + call: Call>, + response: Response> + ) { + println(response.body()) + } + + override fun onFailure(call: Call>, t: Throwable) { + t.printStackTrace() + } + }) + triggerUpdateNext(delay) + } + message.obj = this@HandlerUpdateTask + sendMessageDelayed(message, delay) + } + + override fun scheduleUpdate(interval: Long) { + cancel() + + val handlerThread = HandlerThread("handler-thread") + handlerThread.start() + val handler = Handler(handlerThread.looper) + handler.triggerUpdateNext(interval) + + this.handlerThread = handlerThread + this.handler = handler + } + + override fun cancel() { + handler?.removeCallbacksAndMessages(this) + handler = null + handlerThread?.quit() + handlerThread = null + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/Main.kt new file mode 100644 index 0000000..49268a0 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/Main.kt @@ -0,0 +1,23 @@ +package com.bennyhuo.kotlin.scheduledtask + +import kotlinx.coroutines.delay + +suspend fun main() { + + val taskClasses = listOf( + TimerUpdateTask::class, + RxJavaUpdateTask::class, + HandlerUpdateTask::class, + CoroutineUpdateTask::class + ) + + taskClasses.forEach { + val task = it.java.newInstance() + println("${it.simpleName} start") + task.scheduleUpdate(1000) + delay(5000) + task.cancel() + println("${it.simpleName} cancel") + } + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/RxJavaUpdateTask.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/RxJavaUpdateTask.kt new file mode 100644 index 0000000..65ef939 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/RxJavaUpdateTask.kt @@ -0,0 +1,31 @@ +package com.bennyhuo.kotlin.scheduledtask + +import com.bennyhuo.kotlin.api.updateApi +import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.schedulers.Schedulers +import java.util.concurrent.TimeUnit + +class RxJavaUpdateTask : UpdateTask { + + private var disposable: Disposable? = null + + override fun scheduleUpdate(interval: Long) { + cancel() + + disposable = Observable.interval(interval, TimeUnit.MILLISECONDS) + .observeOn(Schedulers.io()) + .flatMap { + updateApi.getConfigObservable() + }.onErrorResumeNext { + Observable.just(emptyList()) + }.subscribe { + println(it) + } + } + + override fun cancel() { + disposable?.dispose() + disposable = null + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/TimerUpdateTask.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/TimerUpdateTask.kt new file mode 100644 index 0000000..d11ac87 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/TimerUpdateTask.kt @@ -0,0 +1,42 @@ +package com.bennyhuo.kotlin.scheduledtask + +import com.bennyhuo.kotlin.api.Config +import com.bennyhuo.kotlin.api.updateApi +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import java.util.* + +class TimerUpdateTask : UpdateTask { + + private var timer: Timer? = null + + override fun scheduleUpdate(interval: Long) { + cancel() + + val timer = Timer() + timer.schedule(object : TimerTask() { + override fun run() { + updateApi.getConfig().enqueue(object : Callback> { + override fun onResponse( + call: Call>, + response: Response> + ) { + println(response.body()) + } + + override fun onFailure(call: Call>, t: Throwable) { + t.printStackTrace() + } + }) + } + }, 0L, interval) + + this.timer = timer + } + + override fun cancel() { + timer?.cancel() + timer = null + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/UpdateTask.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/UpdateTask.kt new file mode 100644 index 0000000..e36dd43 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/scheduledtask/UpdateTask.kt @@ -0,0 +1,10 @@ +package com.bennyhuo.kotlin.scheduledtask + +interface UpdateTask { + + fun scheduleUpdate(interval: Long) + + fun cancel() + +} + diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/tailrec/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/tailrec/Main.kt new file mode 100644 index 0000000..f336715 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/tailrec/Main.kt @@ -0,0 +1,109 @@ +package com.bennyhuo.kotlin.tailrec + +import kotlin.time.ExperimentalTime +import kotlin.time.measureTime + + +/** + * Created by benny. + */ +@OptIn(ExperimentalTime::class) +fun main() { +// timeCost { factorial(10u) } +// timeCost { factorialTR(10u) } +// timeCost { factorialLoop(10u) } +// +// timeCost { fibonacciTR(1000u) } +// timeCost { fibonacciLoop(1000u) } + timeCost { fibonacci(50u) } +} + +@OptIn(ExperimentalTime::class) +inline fun timeCost(block: () -> Unit) { + measureTime { + block() + }.let { + println(it.inWholeMilliseconds) + } +} + +//region factorial +fun factorial(n: UInt): UInt { + if (n == 0u) return 1u + return n * factorial(n - 1u) +} + +fun factorialTR(n: UInt): UInt { + tailrec fun factorialInner(n: UInt, result: UInt): UInt { + if (n <= 1u) return result + return factorialInner(n - 1u, result * n) + } + return factorialInner(n, 1u) +} + +fun factorialLoop(n: UInt): UInt { + var result = 1u + for (i in 1u..n) { + result *= i + } + return result +} +//endregion + +//region fibonacci +fun fibonacci(n: UInt): UInt { + if (n < 2u) return n + return fibonacci(n - 1u) + fibonacci(n - 2u) +} + +fun fibonacciTR(n: UInt): UInt { + if (n < 2u) return n + + tailrec fun fibonacciInner(n: UInt, a: UInt, b: UInt): UInt { + if (n < 2u) return b + return fibonacciInner(n - 1u, b, a + b) + } + return fibonacciInner(n, 0u, 1u) +} + +fun fibonacciLoop(n: UInt): UInt { + if (n < 2u) return n + + var a = 0u + var b = 1u + for (i in 2u..n) { + val tmp = b + b = a + b + a = tmp + + //region same but confusing + // b = a + b + // a = b - a + //endregion + } + return b +} +//endregion + +//region List +sealed class List { + object Nil : List() + class Cons(val value: T, val next: List) : List() +} + +tailrec fun List.forEach(block: (T) -> Unit) { + when (this) { + List.Nil -> return + is List.Cons -> { + block(value) + next.forEach(block) + } + } +} + +fun listOf(vararg values: T): List { + return values.reversedArray().fold(List.Nil as List) { acc, t -> + List.Cons(t, acc) + } +} +//endregion \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/jvmrecord/JavaRecordSample.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/jvmrecord/JavaRecordSample.java new file mode 100644 index 0000000..e5ecffe --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/jvmrecord/JavaRecordSample.java @@ -0,0 +1,30 @@ +package com.bennyhuo.kotlin.update15.jvmrecord; + +/** + * Created by benny at 2021/6/18 8:06. + */ +public class JavaRecordSample { + + public record Person (String name, int age) { + + public Person { + if (name == null) throw new IllegalArgumentException("name should not be null."); + if (age < 0 || age > 100) throw new IllegalArgumentException(""); + count++; + } + + public static int count = 0; + + public static int count() { + return count; + } + + } + + public static void main(String[] args) { + var person = new Person("bennyhuo", 2); + System.out.println(person); + //var ktPerson = new KotlinPerson("bennyhuo", 10); + } + +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/jvmrecord/JavaRecordSupport.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/jvmrecord/JavaRecordSupport.kt new file mode 100644 index 0000000..3cd27be --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/jvmrecord/JavaRecordSupport.kt @@ -0,0 +1,15 @@ +package com.bennyhuo.kotlin.update15.jvmrecord + +/** + * Created by benny at 2021/6/20 9:35. + */ +open class Super +@JvmRecord +data class KotlinPerson(val name: String, val age: Int) { + +} + +fun main() { + val person = JavaRecordSample.Person("bennyhuo", 1) + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/Cons.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/Cons.java new file mode 100644 index 0000000..8ff2dc5 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/Cons.java @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.javasealed; + +/** + * Created by benny. + */ +public final class Cons implements List{ +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/List.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/List.java new file mode 100644 index 0000000..253f724 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/List.java @@ -0,0 +1,8 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.javasealed; + +/** + * Created by benny. + */ +public sealed interface List permits Nil, Cons { + +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/Nil.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/Nil.java new file mode 100644 index 0000000..dd64d22 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/javasealed/Nil.java @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.javasealed; + +/** + * Created by benny. + */ +public final class Nil implements List { +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_0/List.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_0/List.kt new file mode 100644 index 0000000..35da11d --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_0/List.kt @@ -0,0 +1,32 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_0 + +/** + * Created by benny. + * For Kotlin 1.0 and before. + */ +sealed class List { + object Nil: List() + class Cons(val value: T, val next: List): List() +} + +tailrec fun List.forEach(block: (T) -> Unit) { + when(this) { + List.Nil -> return + is List.Cons -> { + block(value) + next.forEach(block) + } + } +} + +fun listOf(vararg values: T): List { + return values.reversedArray().fold(List.Nil as List) { acc, t -> + List.Cons(t, acc) + } +} + +fun main() { + listOf(1,2,3,4).forEach { + println(it) + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_1/List.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_1/List.kt new file mode 100644 index 0000000..c51c370 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_1/List.kt @@ -0,0 +1,31 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_1 + +/** + * Created by benny. + * For Kotlin 1.1 to 1.4. + */ +sealed class List +object Nil: List() +class Cons(val value: T, val next: List): List() + +tailrec fun List.forEach(block: (T) -> Unit) { + when(this) { + Nil -> return + is Cons -> { + block(value) + next.forEach(block) + } + } +} + +fun listOf(vararg values: T): List { + return values.reversedArray().fold(Nil as List) { acc, t -> + Cons(t, acc) + } +} + +fun main() { + listOf(1,2,3,4).forEach { + println(it) + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Cons.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Cons.kt new file mode 100644 index 0000000..7a0ce55 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Cons.kt @@ -0,0 +1,3 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_5.samepackage + +class Cons(val value: T, val next: List): List diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/List.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/List.kt new file mode 100644 index 0000000..45b835d --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/List.kt @@ -0,0 +1,3 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_5.samepackage + +sealed interface List \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Main.kt new file mode 100644 index 0000000..b2049b5 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Main.kt @@ -0,0 +1,28 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_5.samepackage + +/** + * Created by benny. + */ + + +tailrec fun List.forEach(block: (T) -> Unit) { + when(this) { + Nil -> return + is Cons -> { + block(value) + next.forEach(block) + } + } +} + +fun listOf(vararg values: T): List { + return values.reversedArray().fold(Nil as List) { acc, t -> + Cons(t, acc) + } +} + +fun main() { + listOf(1,2,3,4).forEach { + println(it) + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Nil.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Nil.kt new file mode 100644 index 0000000..8bc4d5b --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/Nil.kt @@ -0,0 +1,3 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_5.samepackage + +object Nil: List diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/X.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/X.java new file mode 100644 index 0000000..dc6c298 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/samepackage/X.java @@ -0,0 +1,7 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_5.samepackage; + +/** + * Created by benny. + */ +//public class X implements List { +//} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/useinterface/List.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/useinterface/List.kt new file mode 100644 index 0000000..fc2b0e0 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedinterfaces/since1_5/useinterface/List.kt @@ -0,0 +1,30 @@ +package com.bennyhuo.kotlin.update15.sealedinterfaces.since1_5.useinterface + +/** + * Created by benny. + */ +sealed interface List +object Nil: List +class Cons(val value: T, val next: List): List + +tailrec fun List.forEach(block: (T) -> Unit) { + when(this) { + Nil -> return + is Cons -> { + block(value) + next.forEach(block) + } + } +} + +fun listOf(vararg values: T): List { + return values.reversedArray().fold(Nil as List) { acc, t -> + Cons(t, acc) + } +} + +fun main() { + listOf(1,2,3,4).forEach { + println(it) + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedwhen/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedwhen/Main.kt new file mode 100644 index 0000000..8a9e088 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/sealedwhen/Main.kt @@ -0,0 +1,39 @@ +package com.bennyhuo.kotlin.update15.sealedwhen + +/** + * Created by benny. + */ + +enum class State { + Idle, Playing, Error +} + +class Song + +sealed interface PlayState { + object Idle: PlayState + class Playing(val song: Song): PlayState + class Error(val throwable: Throwable): PlayState +} + +fun main() { + val state = State.Idle + when (state) { + State.Idle -> { + + } + + State.Playing -> { + + } + } + + val playState: PlayState = PlayState.Idle + when (playState) { + PlayState.Idle -> { + + } + } + + +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/valueclass/ValueClass.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/valueclass/ValueClass.kt new file mode 100644 index 0000000..10caba0 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update15/valueclass/ValueClass.kt @@ -0,0 +1,10 @@ +package com.bennyhuo.kotlin.update15.valueclass + +/** + * Created by benny. + */ + +inline class DurationForLegacy(val value: Long) + +@JvmInline +value class DurationForNew(val value: Long) \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/annotations/Annotations.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/annotations/Annotations.kt new file mode 100644 index 0000000..55835e8 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/annotations/Annotations.kt @@ -0,0 +1,36 @@ +package com.bennyhuo.kotlin.update16.annotations + +import kotlin.reflect.full.findAnnotations + +/** + * Created by benny. + */ +annotation class X + +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class BoxContent + +class Box<@BoxContent T> {} + +@Repeatable +annotation class Tag(val value: String) + +annotation class TagContainer(val value: Array) + +@JvmRepeatable(TagContainer::class) +annotation class Tag1(val value: String) + +@Tag("hello") +@Tag("world") +@Tag("world") +@Tag("world") +@Tag("world") +@Tag("world") +class Abc + +@OptIn(ExperimentalStdlibApi::class) +fun main() { + val x = X() + + Abc::class.findAnnotations(Tag::class).forEach { println(it.value) } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/annotations/JavaAnnotationSample.java b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/annotations/JavaAnnotationSample.java new file mode 100644 index 0000000..3579ed1 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/annotations/JavaAnnotationSample.java @@ -0,0 +1,56 @@ +package com.bennyhuo.kotlin.update16.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Repeatable; + +/** + * Created by benny. + */ +public class JavaAnnotationSample { + + public static void main(String[] args) { + SuperAnnotation annotation = new SubAnnotation("HelloWorld"); + System.out.println(annotation.value()[0]); + } + + public @interface SuperAnnotation { + String[] value(); + } + + static class SubAnnotation implements SuperAnnotation { + private String value; + + public SubAnnotation(String value) { + this.value = value; + } + + @Override + public String[] value() { + return new String[]{value}; + } + + @Override + public Class annotationType() { + return SuperAnnotation.class; + } + } + + @Repeatable(Container.class) + public @interface Tag { + String value(); + } + + + public @interface Container { + Tag[] value(); + } + + @Tag("hello") + @Tag("world") + class Abc { + } + + @Container({@Tag("hello"), @Tag("world")}) + class Acb { + } +} diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/builderinterfaces/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/builderinterfaces/Main.kt new file mode 100644 index 0000000..a2f0c46 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/builderinterfaces/Main.kt @@ -0,0 +1,40 @@ +package com.bennyhuo.kotlin.update16.builderinterfaces + +/** + * Created by benny. + */ +class Container { + fun setValue(value: T) { + + } + + fun getValue(): T = TODO() +} + +fun buildContainer(builder: Container.() -> Unit) { + +} + +fun main() { + buildContainer { + setValue(1) + } + + buildList { + add("Hello") + add("World") + set(1, "World 1") + } + + buildMap { + put("Hello", 1) + } + + buildSet { + add(1) + } + + sequence { + yield(1) + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/sealedwhen/Sample.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/sealedwhen/Sample.kt new file mode 100644 index 0000000..00fc575 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/sealedwhen/Sample.kt @@ -0,0 +1,29 @@ +package com.bennyhuo.kotlin.update16.sealedwhen + +/** + * Created by benny. + */ +sealed class Contact { + data class PhoneCall(val number: String) : Contact() + data class TextMessage(val number: String) : Contact() +} + +//fun Contact.messageCost(): Int = +// when (this) { // Error: 'when' expression must be exhaustive +// is Contact.PhoneCall -> 42 +// } + +fun sendMessage(contact: Contact, message: String) { + // Starting with 1.6.0 + + // Warning: Non exhaustive 'when' statements on Boolean will be + // prohibited in 1.7, add 'false' branch or 'else' branch instead + when (message.isEmpty()) { + true -> return + } + // Warning: Non exhaustive 'when' statements on sealed class/interface will be + // prohibited in 1.7, add 'is TextMessage' branch or 'else' branch instead + when (contact) { + is Contact.PhoneCall -> TODO() + } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/suspendingtype/SuspendingFunctionType.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/suspendingtype/SuspendingFunctionType.kt new file mode 100644 index 0000000..a4086a9 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/suspendingtype/SuspendingFunctionType.kt @@ -0,0 +1,52 @@ +package com.bennyhuo.kotlin.update16.suspendingtype + +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + +/** + * Created by benny. + */ +class MyClickAction0 : () -> Unit { + override fun invoke() { + } + +} + +class MyClickAction1 : suspend () -> Unit { + override suspend fun invoke() { + TODO() + } +} + +fun launchOnClick(action: suspend () -> Unit) {} + +fun getSuspending(suspending: suspend () -> Unit) {} + +fun suspending() {} + +fun test(regular: () -> Unit) { + getSuspending { } // OK + getSuspending(::suspending) // 1.4 OK + getSuspending(regular) // 1.6 OK + + val x: () -> Unit = { } + val y: suspend () -> Unit = { } + + GlobalScope.launch { + + } + + suspend { + + } +} + +fun main() { + launchOnClick(MyClickAction0()) + launchOnClick(MyClickAction1()) + + val clickAction1: suspend () -> Unit = MyClickAction1() + // val clickAction0: suspend () -> Unit = MyClickAction0() + + val x: suspend () -> Unit = { } +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/typeinferring/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/typeinferring/Main.kt new file mode 100644 index 0000000..c47cddb --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/update16/typeinferring/Main.kt @@ -0,0 +1,40 @@ +package com.bennyhuo.kotlin.update16.typeinferring + +/** + * Created by benny. + */ +abstract class AbsBuilder> { + val self: B = this as B + + private var id: Int? = null + + fun setId(id: Int): B { + this.id = id + return self + } +} + +open class MyBuilder1> : AbsBuilder() { + + private var name: String? = null + + fun setName(name: String): B { + this.name = name + return self + } +} + +class MyBuilder2 : MyBuilder1() { + private var age: Int? = null + + fun setAge(age: Int): MyBuilder2 { + this.age = age + return this + } +} + +fun main() { + MyBuilder1().setId(1).setName("Hello") // error < 1.6 + + MyBuilder2().setId(2).setAge(10) +} \ No newline at end of file diff --git a/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/url/Main.kt b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/url/Main.kt new file mode 100644 index 0000000..673cfe2 --- /dev/null +++ b/code/Kotlin-Sample/src/main/java/com/bennyhuo/kotlin/url/Main.kt @@ -0,0 +1,27 @@ +package com.bennyhuo.kotlin.url + +import okhttp3.HttpUrl + +/** + * Created by benny. + */ +fun appendQuery(url: String, name: String, value: String): String { + val httpUrl = HttpUrl.parse(url)!! + println(httpUrl.fragment()) + if (httpUrl.queryParameter(name) == null) { + return httpUrl.newBuilder().addQueryParameter(name, value) + .build().toString() + } else { + return url + } +} + +fun getUrl(): String { + return "http://local.bennyhuo.com:8000/#/index?c=4" +} + +fun main() { + println(appendQuery("http://www.baidu.com", "a", "1")) + println(appendQuery(getUrl(), "c", "3")) +} + diff --git a/code/Kt10/src/main/kotlin/net/println/kt10/kotlin/LazyThreadSafeSynchronized.kt b/code/Kt10/src/main/kotlin/net/println/kt10/kotlin/LazyThreadSafeSynchronized.kt deleted file mode 100644 index 50b3aa1..0000000 --- a/code/Kt10/src/main/kotlin/net/println/kt10/kotlin/LazyThreadSafeSynchronized.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.println.kt10.kotlin - -/** - * Created by benny on 11/13/16. - */ -class LazyThreadSafeSynchronized private constructor(){ - companion object{ - var instance: LazyThreadSafeSynchronized? = null - - @Synchronized - fun getInstance() = { - if(instance == null) instance = LazyThreadSafeSynchronized() - instance!! - } - } -} \ No newline at end of file diff --git a/legacy/README.md b/legacy/README.md new file mode 100644 index 0000000..79f67ac --- /dev/null +++ b/legacy/README.md @@ -0,0 +1,128 @@ +# [Kotlin从入门到『放弃』系列 视频教程](https://github.com/enbandari/Kotlin-Tutorials) + +随着Kotlin越来越成熟稳定,我已经开始在生产环境中使用它。考虑到目前国内资料较少,我录制了一套视频教程,希望以此抛砖引玉,让 Kotlin 在国内火起来。 + +个人水平有限,不足之处欢迎大家发邮件到 [bennyhuo@println.net](mailto: bennyhuo@println.net) ,谢谢大家! + +# 介绍 + +视频从2016年10月初开始发布,更新至12月中旬完结。精力有限,后续暂时每周一通过公众号推送 Kotlin 及 Java 生态的一些文章,大家有选题也可以直接联系我,目前已经有两篇是基于大家的反馈撰写的,反馈也比较不错,谢谢大家的关注与支持。 + +[在线收看全部视频(腾讯视频)](http://v.qq.com/boke/gplay/903446d6231d8612d198c58fb86eb4dc_t6d000101bd9lx1.html) + +[下载全部视频(百度云)](http://pan.baidu.com/s/1nvGYAfB) + +# 目录 + +#### [01 Kotlin 简介](http://v.qq.com/page/z/u/9/z0337i7a3u9.html) + +  简要介绍下什么是 Kotlin,新语言太多了,大家为什么要接触 Kotlin 呢?因为它除了长得与 Java 不太像以外,其他的都差不多~ +   + +#### [02 Hello World](http://v.qq.com/page/h/n/m/h0337jfa5nm.html) + +  千里之行,始于Hello World! +   + +#### [03 使用Gradle编写程序简介(可选)](http://v.qq.com/page/b/p/l/b03372ox4pl.html) + +  这年头,写 Java 系的代码,不知道 Gradle 怎么行呢? +   + +#### [04 集合遍历 map](http://v.qq.com/page/s/q/c/s033707mdqc.html) + +  放下 i++,你不知道 map 已经占领世界了么?以前我以为 map-reduce 很牛逼,后来才知道就是数据迭代处理嘛。 +   + +#### [05 集合扁平化 flatMap](http://v.qq.com/page/h/u/7/h0337scgau7.html) + +  这个可以说是 map 的一个加强版,返回的仍然是开一个可迭代的集合,用哪个您自己看需求~ +   + +#### [06 枚举类型与When表达式](http://v.qq.com/page/t/0/9/t0337iacg09.html) + +  Kotlin 丢掉了 switch,却引进了 when,这二者看上去极其相似,不过后者却要强大得多。至于枚举嘛,还是 Java 枚举的老样子。 + + +#### [07 在 RxJava 中使用 Lambda](http://v.qq.com/x/page/l0340boeng7.html) + +  这一期通过一个统计文章中字符数的小程序进一步给大家呈现 Lambda 的威力,也向大家展示一下如何在 Kotlin 当中优雅地使用 RxJava。我不做教科书,所以如果大家对概念感兴趣,可以直接阅读官方 [API](https://kotlinlang.org/docs/reference/lambdas.html) + +  [RxJava](https://github.com/ReactiveX/RxJava) 是一个非常流行的 Java Reactive 框架,函数式的数据操作使得 Lambda 表达式可以充分体现自己的优势,比起 Java 的冗长,你会看到一段非常漂亮简洁的代码。建议大家先阅读 [RxJava](https://github.com/ReactiveX/RxJava) 的官方文章以对其有一些基本的认识。 +   + +#### [08 使用 Retrofit 发送 GET 请求](http://v.qq.com/x/page/t0342thu1al.html) + +  [Retrofit](https://square.github.io/retrofit/) 是 Square 的 Jake 大神开源的RESTful 网络请求框架,用它发送请求的感觉会让你感觉爽爆的。我这里还有几篇文章,以及一个我 hack 过的分支 [HackRetrofit](https://github.com/enbandari/HackRetrofit),有兴趣的童鞋可以一起探讨下~ + + +* [Android 下午茶:Hack Retrofit 之 增强参数](https://zhuanlan.zhihu.com/p/20863588)). + +* [Android 下午茶:Hack Retrofit (2) 之 Mock Server](https://www.zhihu.com/column/p/21364346) + +* [深入浅出 Retrofit,这么牛逼的框架你们还不来看看?](https://zhuanlan.zhihu.com/p/21808012) + + +#### [09 尾递归优化](http://v.qq.com/x/page/f0345wmuw2m.html) + +  尾递归,顾名思义,就是递归中调用自身的部分在函数体的最后一句。我们知道,递归调用对于栈大小的考验是非常大的,也经常会因为这个导致 StackOverflow,所以尾递归优化也是大家比较关注的一个话题。Kotlin 支持语法层面的尾递归优化,这在其他语言里面是不多见的。 + + +#### [10 单例](https://v.qq.com/x/page/w03659ate6w.html) + +  单例大家一定都不陌生,只要你动手写一个程序,就免不了要设计出一些全局存在且唯一的对象,他们就适合采用单例模式编写。在 Java 里面,单例模式的写法常见的有好几种,虽然简单却也是涉及了一些有意思的话题,那么在 Kotlin 当中我们要怎么设计单例程序呢? + + +#### [11 Sealed Class](https://v.qq.com/x/page/f0350ioskzj.html) +  枚举类型可以很好的限制一个类型的实例个数,比如 State 枚举有两种类型 IDLE 和 BUSY 两种状态,用枚举来描述再合适不过。不过,如果你想要设计子类个数有限的数据结构,比如指令,指令的类型通常是确定的,不过对于某些有参数的指令每一次都使用同一个实例反而不合适,这时候就需要 Sealed Class。 +   +   +#### [12 Json数据引发的血案](https://v.qq.com/x/page/s035296s9nw.html) +  Json 数据可真是大红大紫一番,它实在是太容易理解了,随着 Js 的火爆它就更加『肆无忌惮』起来。我们在 Java/Kotlin 当中解析它的时候经常会用到 Gson 这个库,用它来解析数据究竟会遇到哪些问题?本期主要围绕 Json 解析的几个小例子,给大家展示一下 Java/Kotlin 的伪泛型设计的问题,以及不完整的数据的解析对语言本身特性的冲击。 + + +#### [13 kapt 以及它的小伙伴们](https://v.qq.com/x/page/q035439xksx.html) + +  首先感谢 @CodingPapi,这一期的内容主要来自于他的建议。 + +  Kotiln 对于注解的支持情况在今年(2016)取得了较大的成果,现在除了对 @Inherited 这个注解的支持还不够之外,试用了一下没有发现太大的问题。关于 kapt,官方的文章罗列下来,其中 + +* [kapt: Annotation Processing for Kotlin +](https://blog.jetbrains.com/kotlin/2015/05/kapt-annotation-processing-for-kotlin/) 已经过时了,大家可以阅读下了解其中提到的三个方案 + +* [Better Annotation Processing: Supporting Stubs in kapt +](https://blog.jetbrains.com/kotlin/2015/06/better-annotation-processing-supporting-stubs-in-kapt/) 提到的实现其实基本上就是现在的正式版 + +* [Kotlin 1.0.4 is here +](https://blog.jetbrains.com/kotlin/2016/09/kotlin-1-0-4-is-here/)提到了 kapt 的正式发布,需要注意的是,kapt 的使用方法有些变化,需要 ```apply plugin: 'kotlin-kapt'``` + +  本期主要通过一个简单的 [Dagger2](https://google.github.io/dagger/) 实例给大家展示了注解在 Kotlin 当中的使用,看上去其实与在 Java 中使用区别不大,生成的源码也暂时是 Java 代码,不过这都不重要了,反正是要编译成 class 文件的。 + +  后面我们又简单分析了一下 Dagger2 以及 [ButterKnife](https://github.com/JakeWharton/butterknife) 的源码(有兴趣的话也可以看下我直接对后者进行分析和 Hack 的一篇文章:[深入浅出 ButterKnife,听说你还在 findViewById?](http://www.println.net/post/Deep-in-ButterKnife-3)),其实自己实现一个注解处理器是非常容易的,类似的框架还有[androidannotations](https://github.com/androidannotations/androidannotations),它的源码大家可以自行阅读。 + +**** +通过这个例子,我们其实发现 kapt 还是有一些不完善的地方,主要是: + +1. 不支持 @Inherited +2. 生成的源码需要手动添加到 SourceSets 中 +3. 编译时有时候需要手动操作一下 gradle 的 build 才能生成源码(这一点大家注意下就行了,我在视频中并没有提到) + +不过总体来讲,kapt 的现状还是不错的,相信不久的将来这些问题都将不是问题。 +**** + +#### [14 Kotlin 与 Java 共存 (1)](https://v.qq.com/x/page/c03579nzo8x.html) + +  你想要追求代码简洁、美观、精致,你应该倾向于使用 Kotlin,而如果你想要追求代码的功能强大,甚至有些黑科技的感觉,那 Java 还是当仁不让的。 + +  说了这么多,还是那句话,让他们共存,各取所长。 + +  那么问题来了,怎么共存呢?虽然一说理论我们都知道,跑在 Jvm 上面的语言最终都是要编成 class 文件的,在这个层面大家都是 Java 虚拟机的字节码,可他们在编译之前毕竟还是有不少差异的,这可如何是好? + +  正所谓兵来将挡水来土掩,有多少差异,就要有多少对策,这一期我们先讲**在 Java 中调用 Kotlin**。 + + +#### [15 Kotlin 与 Java 共存 (2)](https://v.qq.com/x/page/z0357ls85fe.html) + +  上一期我们简单讨论了几个 Java 调用 Kotlin 的场景,这一期我们主要讨论相反的情况:如何在 Kotlin 当中调用 Java 代码。 + +  除了视频中提到的点之外还有一些细节,比如异常的捕获,集合类型的映射等等,大家自行参考官方文档即可。在了解了这些之后,你就可以放心大胆的在你的项目中慢慢渗透 Kotlin,让你的代码逐渐走向简洁与精致了。 \ No newline at end of file diff --git "a/legacy/articles/2016.12.26 Kotlin \345\246\202\344\275\225\344\274\230\351\233\205\347\232\204\345\256\236\347\216\260\343\200\216\345\244\232\347\273\247\346\211\277\343\200\217.md" "b/legacy/articles/2016.12.26 Kotlin \345\246\202\344\275\225\344\274\230\351\233\205\347\232\204\345\256\236\347\216\260\343\200\216\345\244\232\347\273\247\346\211\277\343\200\217.md" new file mode 100644 index 0000000..60c429d --- /dev/null +++ "b/legacy/articles/2016.12.26 Kotlin \345\246\202\344\275\225\344\274\230\351\233\205\347\232\204\345\256\236\347\216\260\343\200\216\345\244\232\347\273\247\346\211\277\343\200\217.md" @@ -0,0 +1,109 @@ +Hi,Kotliners,尽管视频完结了,不过每周一我还是会给大家推送一些 Kotlin 的有意思的话题,如果大家对视频有兴趣,直接点击阅读原文就可以找到~ + +[Kotlin 从入门到『放弃』视频教程](https://github.com/enbandari/Kotlin-Tutorials) + +-- + +这一期给大家讲一个有意思的东西。我们都知道 Java 当年高调的调戏 C++ 的时候,除了最爱说的内存自动回收之外,还有一个著名的单继承,任何 Java 类都是 Object 的子类,任何 Java 类有且只有一个父类,不过,它们可以有多个接口,就像这样: + +```java +public class Java extends Language implements JVMRunnable{ + ... +} + +public class Kotlin extends Language implements JVMRunnable, FERunnable{ + ... +} + +``` + +这样用起来真的比 C++ 要简单得多,不过有时候也会有些麻烦:Java 和 Kotlin 都可以运行在 JVM 上面,我们用一个接口 JVMRunnable 来标识它们的这一身份;现在我们假设这二者对于 JVMRunnable 接口的实现都是一样的,所以我们将会在 Java 和 Kotlin 当中写下两段重复的代码: + +```java +public class Java extends Language implements JVMRunnable{ + public void runOnJVM(){ + ... + } +} + +public class Kotlin extends Language implements JVMRunnable, FERunnable{ + public void runOnJVM(){ + ... + } + public void runOnFE(){ + ... + } +} +``` + +重复代码使我们最不愿意看到的,所以我们决定创建一个 JVMLanguage 作为 Java 和 Kotlin 的父类,它提供默认的 runOnJVM 的实现。看上去挺不错。 + +```java +public abstract class JVMLanguage{ + public void runOnJVM(){ + ... + } +} + +public class Java extends JVMLanguage{ + +} + +public class Kotlin extends JVMLanguage implements FERunnable{ + public void runOnFE(){ + ... + } +} +``` + +当然,我们还知道 Kotlin 可以编译成 Js 运行,那我们硬生生的把 Kotlin 称作 JVMLanguage 就有些牵强了,而刚刚我们觉得很完美的写法呢,其实是不合适的。 + +简单的说,继承和实现接口的区别就是:继承描述的是这个类『是什么』的问题,而实现的接口则描述的是这个类『能做什么』的问题。 + +Kotlin 与 Java 在能够运行在 JVM 这个问题上是一致的,可 Java 却不能像 Kotlin 那样去运行在前端,Kotlin 和 Java 运行在 JVM 上这个点只能算作一种能力,而不能对其本质定性。 + +于是我们在 Java 8 当中看到了接口默认实现的 Feature,于是我们的代码可以改改了: + +```java +public interface JVMRunnable{ + default void runOnJVM(){ + ... + } +} + +public class Java extends Language implements JVMRunnable{ + +} + +public class Kotlin extends Language implements JVMRunnable, FERunnable{ + public void runOnFE(){ + ... + } +} +``` + +这样很好,不过,由于接口无法保存状态,runOnJVM 这个方法的接口级默认实现仍然非常受限制。 + +那么 Kotlin 给我们带来什么呢?大家请看下面的代码: + +```kotlin +abstract class Language + +interface JVMRunnable{ + fun runOnJVM() +} + +class DefaultJVMRunnable : JVMRunnable { + override fun runOnJVM() { + println("running on JVM!") + } +} + +class Java(jvmRunnable: JVMRunnable) : Language(), JVMRunnable by jvmRunnable +class Kotlin(jvmRunnable: JVMRunnable) : Language(), JVMRunnable by jvmRunnable, FERunnable{ + fun runOnFE(){ + ... + } +} +``` +通过接口代理的方式,我们把 JVMRunnable 的具体实现代理给了 jvmRunnable 这个实例,这个实例当然是可以保存状态的,它一方面可以很好地解决我们前面提到的接口默认实现的问题,另一方面也能在提供能力的同时不影响原有类的『本质』。 diff --git a/legacy/articles/2016.12.26.jpg b/legacy/articles/2016.12.26.jpg new file mode 100644 index 0000000..09266f8 Binary files /dev/null and b/legacy/articles/2016.12.26.jpg differ diff --git a/legacy/articles/2017.1.16/cover.jpg b/legacy/articles/2017.1.16/cover.jpg new file mode 100644 index 0000000..1be5ef6 Binary files /dev/null and b/legacy/articles/2017.1.16/cover.jpg differ diff --git "a/legacy/articles/2017.1.16/\347\224\250 Kotlin \345\206\231 Android 01 \351\232\276\351\201\223\345\217\252\346\234\211\347\216\257\345\242\203\346\220\255\345\273\272\350\277\231\344\271\210\347\256\200\345\215\225\357\274\237.md" "b/legacy/articles/2017.1.16/\347\224\250 Kotlin \345\206\231 Android 01 \351\232\276\351\201\223\345\217\252\346\234\211\347\216\257\345\242\203\346\220\255\345\273\272\350\277\231\344\271\210\347\256\200\345\215\225\357\274\237.md" new file mode 100644 index 0000000..e44056d --- /dev/null +++ "b/legacy/articles/2017.1.16/\347\224\250 Kotlin \345\206\231 Android 01 \351\232\276\351\201\223\345\217\252\346\234\211\347\216\257\345\242\203\346\220\255\345\273\272\350\277\231\344\271\210\347\256\200\345\215\225\357\274\237.md" @@ -0,0 +1,298 @@ +# [用 Kotlin 写 Android] 01 难道只有环境搭建这么简单? + +从这周开始,每周一的文章推送将连载 Kotlin Android 开发的文章,大家有关心的题目也可以直接反馈给我,这样也可以帮助我提高后续文章的针对性。 + +亲爱的小伙伴,阅读本文之前,请确保你对 Kotlin 有一定的了解,并且你的 Android Studio 或者 IntelliJ Idea 已经安装了 Kotlin 的插件。如果没有,果断回去先看我的 [Kotlin 视频](https://github.com/enbandari/Kotlin-Tutorials) 第一集 :) + +## 1 千里之行,始于 Hello World + +话说我们入坑 Kotlin 之后,要怎样才能把它运用到 Android 开发当中呢?我们作为有经验的开发人员,大家都知道 Android 现在基本上都用 gradle 构建,gradle 构建过程中只要加入 Kotlin 代码编译的相关配置,那么 Kotlin 的代码运用到 Android 的问题就解决了。 + +这个问题有何难呢?Kotlin 团队早就帮我们把这个问题解决了,只要大家在 gradle 配置中加入: + +```groovy +apply plugin: 'kotlin-android' +``` + +就可以了,这与我们在普通 Java 虚拟机的程序的插件不太一样,其他的都差不多,比如我们需要在 buildScript 当中添加的 dependencies 与普通 Java虚拟机程序毫无二致: + +```groovy +buildscript { + ext.kotlin_version = '1.0.6'//版本号根据实际情况选择 + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} +``` +当然,我们还要在应用的 dependencies 当中添加 Kotlin 标准库: + +```groovy +compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" +``` + +有了这些,你的 Kotlin 代码就可以跑在 Android 上面了!当然,你的代码写在 src/main/java 或是 src/main/kotlin 下都是可以的。这不重要了,我觉得把 Java 和 Kotlin 代码混着写就可以了,没必要分开,嗯,你最好不要感觉到他们是两个不同的语言,就酱紫。 + +```Kotlin +package net.println.kotlinandroiddemo + +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.widget.TextView + +class MainActivity : AppCompatActivity() { + + private lateinit var textView: TextView + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + textView = findViewById(R.id.hello) as TextView + textView.text = "Hello World" + } +} +``` + +我们定义一个 TextView 的成员,由于我们只能在 onCreate 当中初始化这个成员,所以我们只好用 lateinit 来修饰它。当然,如果你不怕麻烦,你也可以选择 TextView? ,然后给这个成员初始化为 null。 + +接着我们就用最基本的写法 findViewById、类型强转拿到这个 textView 的引用,然后 setText。 + +运行自然是没有问题的。 + +不过,不过!我如果就写这么点儿就想糊弄过去这一周的文章,番茄鸡蛋砸过来估计够我吃一年的西红柿炒鸡蛋了吧(我~就~知~道~,我这一年不用愁吃的了!) + +## 2 Anko 已经超神 + +要说用 Kotlin 写 Android,Anko 谁人不知谁人不晓,简直到了超神的地步。好好,咱们不吹牛了,赶紧把它老人家请出来: + +```groovy +compile 'org.jetbrains.anko:anko-sdk15:0.9' // sdk19, sdk21, sdk23 are also available +compile 'org.jetbrains.anko:anko-support-v4:0.9' // In case you need support-v4 bindings +compile 'org.jetbrains.anko:anko-appcompat-v7:0.9' // For appcompat-v7 bindings +``` + +稍微提一句 anko-sdk 的版本选择: + +* org.jetbrains.anko:anko-sdk15 : 15 <= minSdkVersion < 19 +* org.jetbrains.anko:anko-sdk19 : 19 <= minSdkVersion < 21 +* org.jetbrains.anko:anko-sdk21 : 21 <= minSdkVersion < 23 +* org.jetbrains.anko:anko-sdk23 : 23 <= minSdkVersion + +当然除了这些之外,anko 还对 cardview、recyclerview等等做了支持,大家可以按需添加,详细可以参考 [Github - Anko](https://github.com/Kotlin/anko) + +另外,也建议大家用变量的形式定义 anko 库的版本,比如: + +```groovy +ext.anko_version = "0.9" +... + +compile "org.jetbrains.anko:anko-sdk15:$anko_version" // sdk19, sdk21, sdk23 are also available +compile "org.jetbrains.anko:anko-support-v4:$anko_version" // In case you need support-v4 bindings +compile "org.jetbrains.anko:anko-appcompat-v7:$anko_version" // For appcompat-v7 bindings +``` + +好,有了 Anko 我们能干什么呢? + +```kotlin +textView = find(R.id.hello) +``` +还记得 findViewById 么?变成 find 了,而且强转也没有了,是不是很有趣?你一定有疑问,Anko 究竟干了啥,一下子省了这么多事儿,我们跳进去看看 find 的真面目: + +```kotlin +inline fun View.find(id: Int): T = findViewById(id) as T +inline fun Activity.find(id: Int): T = findViewById(id) as T +inline fun Fragment.find(id: Int): T = view?.findViewById(id) as T +``` + +首先它是个扩展方法,我们暂时只用到了 Activity 的扩展版本,实际上 View、Fragment 都有这个扩展方法;其次,它是个 inline 方法,并且还用到了 reified 泛型参数,我们本来应该这么写: + +```kotlin +textView = find(R.id.hello) +``` +由于泛型参数的类型可以很容易的推导出来,所以我们再使用 find 的时候不需要显式的注明。 + +说到这里,其实还是有问题没有说清楚的,reified 究竟用来做什么?其实我们就算不写 inline 和 reified 泛型,这个方法照样是可以用的: + +```kotlin +fun Activity.myFind(id: Int): T = findViewById(id) as T +``` + +```kotlin +textView = myFind(R.id.hello) +``` + +不过呢,这地方用 inline 就省了一次函数调用,并且 reified 也可以消除 IDE 的类型检查提示,所以既然可以,为什么不呢? + +当然,用 Anko 的好处不可能就这么点儿,我们今天先按住不说,谁好奇的话可以先自己去看看(我~就~知~道~,你们肯定忍不住!!)~ + +## 3 不要 findViewById + +作为第一篇介绍 Kotlin 写 Android 的文章,绝对不能少的就是 kotlin-android-extensions 插件了。在 gradle 当中加配置: + +```groovy +apply plugin: 'kotlin-android-extensions' +``` + +之后,我们只需要在 Activity 的代码当中直接使用在布局中定义的 id 为 hello 的这个 textView,于是: + +```kotlin +import android.os.Bundle +import android.support.v7.app.AppCompatActivity + +//这个包会自动导入 +import kotlinx.android.synthetic.main.activity_main.* + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + //直接使用 hello,hello 实际上是这个view 在布局当中的id + hello.text = "Hello World" + } +} +``` + +只要布局添加一个 View,在 Activity、View、Fragment 中其实都可以直接用 id 来引用这个 view,超级爽~ + +所以,你们不准备问下这是为什么吗?为什么可以这样做呢? + +其实要回答这个问题也不难,首先 Android Studio 要能够从 IDE 的层面索引到 hello 这个 View,需要 Kotlin 的 IDE 插件的支持(别问我啥是 IDE 插件,你们用 Kotlin 的第一天肯定都装过);其次,在编译的时候,编译器能够找到 hello 这个变量,那么还需要 Kotlin 的 gradle 插件支持(我们刚刚好像 apply 了个什么 plugin 来着?)。知道了这两点,我们就要有的放矢了~ + +>“啊!” 那边的 Kotlin 源码一声惨叫。。。 + +前方高能。。我们讨论的源码主要在 plugins 目录下的 android-extensions-compiler 和 android-extensions-idea 两个模块当中。 + +如果让大家自己实现一套机制来完成上面的功能,大家肯定会想,我首先得解析一下 XML 布局文件吧,并把里面的 View 存起来,这样方便后面的查找。我告诉大家,Kotlin 也是这么干的! + +**AndroidXmlVisitor.kt** + +```kotlin +override fun visitXmlTag(tag: XmlTag?) { + ... + + val idAttribute = tag?.getAttribute(AndroidConst.ID_ATTRIBUTE) + if (idAttribute != null) { + val idAttributeValue = idAttribute.value + if (idAttributeValue != null) { + val xmlType = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.value ?: localName + val name = androidIdToName(idAttributeValue) + if (name != null) elementCallback(name, xmlType, idAttribute) + } + } + tag?.acceptChildren(this) +} +``` +这是遍历 XML 标签的代码,典型的访问者模式对吧。如果拿到这个标签,它有 android:id 这个属性,那么小样儿,你别走,老实交代你的 id 是什么!举个例子,如果这个标签是这样的: + +```xml +