Kotlin编程第一课--(基础篇)12 实战:用Kotlin实现一个网络请求框架KtHttp
在前面几节课当中,我们一起学习了 Kotlin 的委托、泛型、注解、反射这几个高级特性。那么今天这节课,我们将会运用这些特性,来写一个 Kotlin 版本的 HTTP 网络请求框架。由于它是纯 Kotlin 开发的,我们就把它叫做是 KtHttp 吧。
事实上,在 Java 和 Kotlin 领域,有许多出色的网络请求框架,比如 OkHttp、Retrofit、Fuel。而我们今天要实现的 KtHttp,它的灵感来自于 Retrofit。之所以选择 Retrofit 作为借鉴的对象,是因为它的底层使用了大量的泛型、注解和反射的技术。如果你能跟着我一起用泛型、注解、反射来实现一个简单的网络请求框架,相信你对这几个知识点的认识也会更加透彻。
在这节课当中,我会带你从 0 开始实现这个网络请求框架。和往常一样,为了方便你理解,我们的代码会分为两个版本:
1.0 版本,我们会用 Java 思维,以最简单直白的方式来实现 KtHttp 的基础功能——同步式的 GET 网络请求;
2.0 版本,我们会用函数式思维来重构代码。
另外,在正式开始学习之前,我也建议你去 clone 我 GitHub ...
Kotlin编程第一课--(基础篇)11 注解与反射:进阶必备技能
今天这节课,我们来学习一下 Kotlin 的注解(Annotation)和反射(Reflection)。
注解和反射,是 Kotlin 当中比较难理解的内容了。和前面我们学习的泛型一样,注解与反射都是比较抽象的概念。我们现在已经知道,Kotlin 的泛型,就是在代码架构的层面进行的一种抽象,从而达到代码逻辑尽可能复用的目的。那么,注解与反射,它们存在的意义是什么呢?
答案是:提高代码的灵活性。
灵活性,就让注解与反射同样有着举足轻重的地位,借助这两种技术,我们可以做许多有趣的事情。Kotlin 与 Java 领域,有许多著名的开源库,比如大名鼎鼎的Spring Boot、Retrofit、Gson等,都会用到这两种技术。
所以,只有深刻理解了注解和反射,我们才可能理解那些著名开源库的设计思路,也才可能读懂这些世界顶级开发者的代码。
当然,课程进行到这里,学习的难度也越来越高了,不过你也不要因此产生畏难的情绪,只要你能多思考、多练习,把对知识点的理解都落实到代码上,那我相信你对 Kotlin 的掌握情况、代码能力甚至架构能力,都会有一个质的飞跃。并且,在课程中我也会尽量用通俗易懂的语言、 ...
Kotlin编程第一课--(基础篇)10 泛型:逆变or协变,傻傻分不清?
这节课我们来学习 Kotlin 的泛型(Generics),包括泛型基础、使用处型变、声明处型变以及星投影。
泛型,这个概念在很多编程语言里面都存在。在中大型软件开发当中,我们对泛型的使用也十分频繁,因为它可以让我们在不同类型之间复用相似的逻辑代码。
不管是 Android 领域,还是后端领域,泛型在软件的架构当中都有着举足轻重的地位。只有透彻理解了泛型,我们才能理解各种设计模式,进而才可能设计出合理的软件架构。
然而,想要学好泛型却不是一件容易的事情。这是因为,泛型实在太抽象了。
我们都知道,程序其实是对真实世界的抽象,比如我们在前面实战课里写的计算器程序,现实生活当中就有计算器这个东西,我们想要在电脑里写一个抽象的计算器程序,也不会那么难理解,因为它和现实生活相关。可是泛型,它是对程序的抽象。程序本来就已经够抽象了,我们还要在它的基础上再做一次抽象。
这样一来,泛型和我们真实的物理世界差了两层抽象,因此,泛型对于我们人类来说,会显得尤为虚无缥缈。
不过,程序其实也是源自于生活的。所以在这节课里,我会尽量用生活中的例子来给你解释下 Kotlin 的泛型概念,让你能更直观、更立体 ...
Kotlin编程第一课--(基础篇)09 委托:你为何总是被低估?
今天我们来学习 Kotlin 的委托特性。
Kotlin 的委托主要有两个应用场景,一个是委托类,另一个是委托属性。对比第 6 讲我们学过的扩展来看的话,Kotlin 委托这个特性就没有那么“神奇”了。
因为扩展可以从类的外部,为一个类“添加”成员方法和属性,因此 Kotlin 扩展的应用场景也十分明确,而 Kotlin 委托的应用场景就没那么清晰了。这也是很多人会“重视扩展”,而“轻视委托”的原因。
然而,我要告诉你的是,Kotlin“委托”的重要性一点也不比“扩展”低。Kotlin 委托在软件架构中可以发挥巨大的作用,在掌握了 Kotlin 委托特性后,你不仅可以改善应用的架构,还可以大大提升开发效率。
另外,如果你是 Android 工程师,你会发现 Jetpack Compose 当中大量使用了 Kotlin 委托特性。可以说,如果你不理解委托,你就无法真正理解 Jetpack Compose。
看到这里,想必你也已经知道 Kotlin 委托的重要性了,接下来就来开启我们的学习之旅吧!
委托类我们先从委托类开始,它的使用场景非常简单易懂:它常常用于实现类的“委托模式”。我们来看 ...
Kotlin编程第一课--(基础篇)加餐一 初识Kotlin函数式编程
在上一节实战课当中,我们算是用 Kotlin 实践了一把函数式编程的思想。不过,上节课我们其实只是浅尝辄止,也不完全算是函数式编程,咱们只是借鉴了它的思想。
函数式编程(Functional Programming),是一个跟“面向对象”类似的概念,它也是软件工程中的一种编程范式,它是声明式编程(Declarative Programming)的一种,而与它相反的,我们叫做命令式编程(Imperative Programming)。
虽然说,Kotlin 的函数式编程还不属于主流,但近几年它的关注度也越来越高了,所以今天我们就借着这节加餐,一起来简单聊聊 Kotlin 的函数式编程,也为上一节实战课做一个延伸。这样,等将来你想深入研究 Kotlin 函数式编程的时候,有了这节课的认知基础,也会更加轻松。
函数式与命令式的区别那么,在介绍函数式编程之前,我们首先要来看几个编程范式的概念:声明式、命令式,还有四个常见的编程范式:函数式、逻辑式、面向过程、面向对象。它们之间的关系大致如下图所示:
我们的校园里学习编程的时候,一般都是学的 C、Java,它们分别是面向过程语言、面向对象语言 ...
Kotlin编程第一课--(基础篇)08 实战:用Kotlin写一个英语词频统计程序
前面几节课,我们学了一些 Kotlin 独有的特性,包括扩展、高阶函数等等。虽然我在前面的几节课当中都分别介绍了这些特性的实际应用场景,但那终归不够过瘾。因此,这节课我们来尝试将这些知识点串联起来,一起来写一个“单词词频统计程序”。
英语单词的频率统计,有很多实际应用场景,比如高考、研究生考试、雅思考试,都有对应的“高频词清单”,考生优先突破这些高频词,可以大大提升备考效率。那么这个高频词是如何统计出来的呢?当然是通过计算机统计出来的。只是,我们的操作系统并没有提供这样的程序,想要用这样的功能,我们必须自己动手写。
而这节课,我将带你用 Kotlin 写一个单词频率统计程序。为了让你更容易理解,我们的程序同样会分为三个版本。
1.0 版本:实现频率统计基本功能,使用“命令式风格”的代码。
2.0 版本:利用扩展函数、高阶函数来优化代码,实现“函数式风格”的代码。
3.0 版本:使用 inline 进一步提升软件的性能,并分析高阶函数的实现原理,以及 inline 到底能带来多大的性能提升。
在正式开始学习之前,我也建议你去 clone 我 GitHub 上面的 TextProces ...
Kotlin编程第一课--(基础篇)07 高阶函数:为什么说函数是Kotlin的“一等公民”?
高阶函数在 Kotlin 里有着举足轻重的地位。它是 Kotlin 函数式编程的基石,是各种框架的关键元素。高阶函数掌握好了,我们理解协程的 launch、async 函数就会轻松一些,阅读协程的源代码也会不那么吃力;高阶函数理解透彻了,我们学习 Jetpack Compose 也会得心应手,在特定业务场景下,我们甚至可以用它来实现自己的 DSL(Domain Specific Language)。
不过,如果你没有函数式编程的相关经验,在初次接触高阶函数的时候,很可能会被绕晕。因为它是一个全新的概念,你很难从经典的 C/Java 里找到同等的概念迁移过来(Java 从 1.8 开始才引入相关概念)。然而,对于高阶函数这么重要的概念,Kotlin 官方文档又惜字如金。
文档里只是突兀地介绍了高阶函数、函数类型、Lambda 表达式的简单用法,接着就丢出一段复杂的代码案例,然后丢出一个更复杂的概念,“带接收者的函数类型”(Function Types With Receiver),接着又丢出了一段更复杂的代码案例。说实话,这真的让人难以理解。
所以今天这节课,我会采用 Java ...
Kotlin编程第一课--(基础篇)06 扩展:你的能力边界到底在哪里?
Kotlin 的扩展(Extension),主要分为两种语法:第一个是扩展函数,第二个是扩展属性。从语法上看,扩展看起来就像是我们从类的外部为它扩展了新的成员。
这在实际编程当中是非常有用的功能。我们可以来想象一个场景:我们想修改 JDK 当中的 String,想在它的基础上增加一个方法“lastElement()”来获取末尾元素,如果使用 Java,我们是无法通过常规手段实现的,因为我们没办法修改 JDK 的源代码。任何第三方提供的 SDK,我们都无权修改。
不过,借助 Kotlin 的扩展函数,我们就完全可以在语义层面,来为第三方 SDK 的类扩展新的成员方法和成员属性。不管是为 JDK 的 String 增加新的成员方法,还是为 Android SDK 的 View 增加新成员属性,我们都可以实现。
Kotlin 的这个“扩展”功能看起来很神奇,它会不会很难学?其实不然,它的语法非常简洁。今天这节课,我们就一起来学习下 Kotlin 当中的扩展。通过研究它的原理,来探索它的能力边界,并在理解和掌握核心知识点之后,去思考它的实战应用场景。
什么是扩展函数和扩展属性?扩展函数,就是从 ...
Kotlin编程第一课--(基础篇)05 object关键字:你到底有多少种用法?
这节课我们来学习 Kotlin 当中 object 关键字的三种语义,以及它的具体使用场景。
在前面课程中,我们学习了 Kotlin 语言的基础语法和面向对象相关的语法,其中涵盖了很多不同类型的关键字。比如说,fun 关键字代表了定义函数,class 关键字代表了定义类,这些都是一成不变的。但是今天我们要学习的 object 关键字,却有三种迥然不同的语义,分别可以定义:
匿名内部类;
单例模式;
伴生对象。
之所以会出现这样的情况,是因为 Kotlin 的设计者认为,这三种语义本质上都是在定义一个类的同时还创建了对象。在这样的情况下,与其分别定义三种不同的关键字,还不如将它们统一成 object 关键字。
那么,理解 object 关键字背后的统一语义,对我们学习这个语法是极其关键的,因为它才是这三种不同语义背后的共同点。通过这个统一语义,我们可以在这三种语义之间建立联系,形成知识体系。这样,我们在后面的学习中才不会那么容易迷失,也不会那么容易遗忘。
接下来,我们就一起来逐一探讨这三种情况吧。
object:匿名内部类首先是 object 定义的匿名内部类。
Java 当中其实也 ...
Kotlin编程第一课--(基础篇)04 | 实战:构建一个Kotlin版本的四则运算计算器
前面几节课,我们学了不少 Kotlin 的语法,也算是对 Kotlin 有了一个基本认识。不过,单纯只认识 Kotlin 是远远不够的,我们还要会用 Kotlin。当遇到一个具体问题的时候,我们得能用 Kotlin 来解决这个问题。换句话说,就是要实战。在实战的过程中,我们对 Kotlin 的理解也会进一步加深。
那么这节课,我们就把前面的知识点串联起来,一起做一个 Kotlin 版本的计算器。为了便于理解,我会以循序渐进的方式来编写这个计算器程序,由简单到复杂。你在这个由易到难的实操过程中,可以实际体会到 Kotlin 的代码实现思路以及编码方式的变化,进而也就能更好地掌握和运用前面所学的基础语法,以及与面向对象相关的知识点。
这个计算器程序大致会分为三个版本:
计算器 1.0,实现两个整数的“加减乘除”,对输入数据有严格要求。
计算器 2.0,对输入数据无严格要求,融入面向对象的编程思想。
计算器 3.0,支持“大数的加法”,增加单元测试。
现在,我们就开始实战吧。
创建 Kotlin 工程如果你之前没有使用过 IntelliJ 或 Android Studio,你可能还不知道 ...