写了好长时间的移动端程序,都是基于 Java 的,时代在改变,现在有好多 Kotlin 的示例,虽然不一定以后会用到 Kotlin 去构建工程,但是不好说会有需要参考的 Kotlin 示例,直接看 Kotlin 的工程感觉有点吃力,学一点新的语言,丰富一下自己的技术宽度。
注:以下示例都是基于 Android 平台
For 循环
循环是编程的基础,尤其是 for 循环和 while 循环,Kotlin 的循环表现形式上与 Java 稍有不同
var set = setOf<String>("1xx", "222a", "wq3")
var arr = arrayOf("as2", "3s3", "11c4");
for (i in set) { //区间的表现形式
Log.e("XXX", "i = " + i);
set[i]; // 编译报错,直接使用集合时,并不知道是否可行
}
for (j in arr.indices) { //下标遍历的表现形式
Log.e("XXX", "j = " + j);
arr[j];
Log.e("XXX", "j ele = " + arr[j]); //编译、运行正常
}
for ((i, item) in arr.withIndex()) { //下标和元素同时遍历
Log.e("XXX", "" + i + " ele = " + item);
}
kotlin 给我的感觉是比较轻类型重功能的语言,在使用时要自行关注对象的类型
还记得,以前在嵌套 for 循环的时候,就想过,一个 break 可以跳出几层循环,当时 Java 能做到的是一层,kotlin 在这方面有很大的自由,可以通过标签,控制跳出哪一层循环
fun testFun() {
loop@for (i in 1 .. 10) {
Log.e("XXX", "i=" + i);
for (j in 20 .. 30) {
if (j >25) break@loop
Log.e("XXX", "j=" + j);
}
}
Log.e("XXX", "end");
}
通过上面的示例代码,可以跑出如下的结果,从内层循环,直接跳到最外层循环的结束
Kotlin 类和对象
private // 仅在同一个文件中可见
protected // 同一个文件中或子类可见
public // 所有调用的地方都可见
internal // 同一个模块中可见
看了一遍下来,Kotlin 对于类的处理,真的是到能多省就多省的地步了,get/set 方法在没有使用注解的前提下都可以不用定义,调用的时候没有实体的 get/set 方法
class Student(testName : String) //主要构造函数
{
var name : String = ""
get() = field // get 方法;如果在属性的结尾加了 ; 后续的 get/set 方法,将不能识别
set(value) { // set 方法
field = value
}
var age : Int = 0 //属性默认 public
get() = field // get 方法不能设置成 private 类型,但是 set 方法可以,设置 private 以后,外部使用处,不可以赋值;同时需要关注,set/get 方法内部使用的是 field 不是,set 方法直接调用 this.变量=XXX 会变成死循环,因为会继续调用 set 方法
set(value) {
field = value
}
lateinit var className : String //lateinit 延迟初始化的关键字,表示该字段会在初始化的时候进行赋值操作
//var sex : Int = null; // 定义要求必须赋值,且非空,可使用 ? 符号,进行自动判空,或者 lateinit 关键字
// 主构造函数的初始化
init {
this.name = testName;
}
//1、次要构造函数,构造函数关键字 "constructor"
//2、如果类有主构造函数,每个次构造函数都要,或直接或间接通过另一个次构造函数代理主构造函数
//3、没有主构造函数,就会没有上述 2 的限制
constructor(name : String, age : Int) : this(name) { //调用其他构造函数的方法
this.age = age;
}
fun transAge(trans : Int): Int{
return age + trans;
}
}
//调用处
{
var stu : Student = Student("hah", 12);
stu.name = "testName" //set 方法
//stu.age = 20; // set 方法设置 private(私有),即不能使用赋值操作
}
一开始看到类里面的 open 关键字有点懵(这个 open 是什么鬼,为什么会有这种东西,这是干嘛的),知道机制以后,才明白,原来 kotlin 的规则下所有的类默认都是 final(java 的 final 哈) 类型,就意味着不能被继承,而且类中所有的方法也是默认 final,意思就是默认不能继承,要实现继承,需要为类增加 open,类就可以被继承了,方法同理
open class BaseKClass {
open fun func() {}
}
class NewBaseKClass : BaseKClass() {
override fun func() {
}
}
匿名类是一种提供内部钩子的方式,实际在解耦处理中比较常见
open class AClass {
var v = "成员变量"
open fun function(param : TestInterface) {
//Log.e("XXX", "function---");
param.test()
}
}
interface TestInterface {
fun test()
}
//调用处
{
var ac : AClass = AClass();
ac.function(object : TestInterface{
override fun test() {
Log.e("XXX", "TestInterface---");
}
})
}
继承是面向对象语言的必须需要掌握的知识点,Kotlin 在继承上的特性有一些点需要注意
1、出现两个被继承的类都有同样的方法时,强制重写同名的方法
2、出现两个被继承的类都有同样的方法时,通过 super 关键字调用父类的实现,需要指定是哪一个父类;没有同方法的父类可以不指定
3、Kotlin 中所有类都继承该 Any 类,它是所有类的超类,对于没有超类型声明的类是默认超类,但是,Any 不是 java.lang.Object
interface AInterface {
fun func() { //接口内的方法是可以有实现的,这点和 Java 区别比较大
Log.e("XXX", "AInterface func")
}
}
open class ABase {
var name : String? = null;
open fun func() {
Log.e("XXX", "ABase func")
}
open fun a() {
Log.e("XXX", "ABase a")
}
}
class AChild : ABase(), AInterface{
var chiledName : String? = null
override fun func() { //出现两个被继承的类都有同样的方法时,强制重写同名的方法
super<ABase>.func();
}
fun aa() {
super<ABase>.func(); //出现两个被继承的类都有同样的方法时,通过 super 关键字调用父类的实现,需要指定是哪一个父类;没有同方法的父类可以不指定
super<AInterface>.func();
}
}
Kotlin 简化了枚举的定义和使用,常用定义示例如下
enum class EnumTest(value : Int) {
A(1),
B(2),
C(3);
}