一、Kotlin变量和函数
1.1 变量
Kotlin中的变量声明有两种,它们分别是:val和var
- val是用来声明一个不可变的变量,相当于Java语言中使用final关键字修饰的变量;
- var是用来声明一个可变的变量。
kotlin中的变量在没赋值前,并不清楚当前变量的类型,只有赋值之后才知道它的类型,Kotlin这种机制叫做类型推到机制。
// 声明一个不可变的变量,它的变量名为a,根据初始化的值10,我们可以推导出它的类型为Int类型,当想改变它的值时,编译器会报错
val a = 10
// 声明一个变量,变量名为b,根据初始化的值,我们可以推导出它的类型为String类型,当再次改变它的值时,直接赋值即可
var b = ""
kotlin也可以显式的声明变量的类型,方法则是在变量名的后边加冒号和要声明的类型
// 显式声明一个不可变的变量,它的变量名为c,它的类型为Int类型,它的默认值为0
val c : Int = 0
// 显式声明一个可变的变量,它的变量名为d,它的类型为Float类型,它的默认值为0f
var d : Float = 0f
变量的使用技巧是优先使用val,当val不满足自己的需求时,再将变量的修饰符修改为var,这样程序会更加健壮。
1.2 函数
函数在Kotlin中声明是使用fun这个关键字来修饰的,然后是函数名,命名方式没有其它要求,最好还是首字母小写,下来是小括号,括号里面是声明函数的入参,接着是冒号以及该函数要返回的返回值类型,最后是大括号,即函数体。
/**
* 我的第一个无参无返回值函数
*/
fun myFirstFun(){
}
/**
* 我的第二个有参有返回值函数
* 参数名为value,参数类型为Int
* 返回值类型也为Int
*/
fun mySecondFun(value: Int) : Int {
return value
}
Kotlin函数的语法糖,当函数的函数体只有一行代码时,Kotlin会允许该函数没有函数体,只需将函数的这一行代码写在函数声明的后面,并使用赋值符号连接即可,上述方法二使用Kotlin函数的语法糖后的声明为:
/**
* 我的第二个有参有返回值函数
* 参数名为value,参数类型为Int
* 返回值类型也为Int
*/
fun mySecondFun(value: Int) : Int = value
二、Kotlin程序的逻辑控制
2.1 if语句
返回两个整型数字中较大的一个,使用if语句实现如下:
fun largerNumber(numberOne: Int,numberTwo: Int) = if (numberOne > numberTwo) numberOne else numberTwo
2.2 when语句
when语句相当于Java语言中的switch语句,但是它又比switch语句强大。
- switch语句只能传入整型或短于整型的变量作为条件,还有String,但是when语句就不收这个限制;
- 还有就是switch语句每个case条件后,要加break,kotlin的when语句就不需要。
查询学生的考试分数的方法使用kotlin的when语句如下:
/**
* 输入学生姓名,返回该学生的成绩
*/
fun getScore(name: String): Int = when (name){
"xiaoming" -> 100
"xiaohong" -> 99
"xiaoliang" -> 95
else -> 0
}
类型匹配使用when语句实现如下:
/**
* 数字类型匹配
*/
fun checkNumber(number: Number) {
when(number){
is Int -> println("The number is Int.")
is Double -> println("The number is Double.")
else -> println("The number not support")
}
}
2.3 for循环语句
要介绍循环,得先学习Kotlin中的区间,升序的区间声明如下:
// 定义一个区间,该区间的名字为range,它的范围是0到10,包括0和10
val range = 0..10
遍历区间的代码如下:
//遍历range这个区间
for (i in range){
println(i)
}
左闭右开区间
//左闭右开区间,范围是0到10,包括0,不包括10
val rangeOne = 0 until 10
一个步数为2的区间遍历如下: 当然想让步数改变就将step后边的数字改变即可
for (i in rangeOne step 2){
println(i)
}
降序区间的声明和遍历如下:
//遍历降序区间
val arr = 30 downTo 1
for(i in arr){
println(i)
}
三、Kotlin是面向对象编程
编程可以分为面向过程和面向对象两种编程语言,Kotlin则是面向对象的编程语言,而我们熟知的C是面向过程的编程语言,那面向过程的语言和面向对象的语言都是怎么定义的呢?
面向过程:是将程序看做一系列的步骤或过程的集合,每个步骤或过程则完成一个特定的任务,这些过程按照一定顺序被调用,以实现整个程序的功能,这就是面向过程的语言。
面向对象:是通过程序将物体或事物封装成一个一个的类,当我们要实现整个程序的功能时,可以使用这些类创建对象,通过这些对象的属性和函数来实现功能。
3.1 类和对象
创建Person类
class Person {
var name = ""
var age = 0
fun eat(){
println(name + " 正在吃饭," + "他" + age + "岁了。")
}
}
下面是实例化一个Person对象,并给他的属性赋值,和调用它的函数。
val p = Person()
p.name = "哪吒"
p.age = 3
p.eat()
3.2 继承和构造函数
创建一个Student类,并让它继承Person类。
- 让Person类可以被继承;
- 让Student类继承Person类,方法则是在Student类后加上冒号和Person即可。
class Student : Person() {
//学号
var id = ""
//年级
var grade = 3
}
Kotlin中的构造函数分为主构造函数和次构造函数。
每个类默认会有个不带参数的主构造函数,主构造函数也可以显式的指明参数,主构造函数的特点是没有函数体
下面是Student带参数的主构造函数
class Student(val id: String,val grade: Int) : Person() {
init {
println("该学生的学号是:$id")
println("该学生的班级是:$grade")
}
}
给Person类也添加个带参的主构造函数
open class Person(val name : String,val age : Int) {
init {
println("这个人的名字是:$name")
println("这个人的年龄是:$age" + "岁")
}
}
此时Student类就会报错,为了解决这个问题,Student就得修改为以下样式
class Student(val id: String,val grade: Int,name: String,age: Int) : Person(name,age) {
init {
println("该学生的学号是:$id")
println("该学生的年级是:$grade" + "年级")
}
}
创建一个Student类的对象就是如下:
//创建一个Student类的对象
val student = Student("20110422",4,"哪吒",3)
运行一下程序控制台将显示以下内容:
这个人的名字是:哪吒
这个人的年龄是:3岁
该学生的学号是:20110422
该学生的年级是:4年级
次构造函数的特点是,它是有函数体的,而且它还必须调用主构造函数,它得使用constructor关键字修饰
Student类添加两个次构造函数后,代码如下:
class Student(val id: String, val grade: Int, name: String, age: Int) : Person(name, age) {
init {
println("该学生的学号是:$id")
println("该学生的年级是:$grade" + "年级")
}
//这个次构造函数创建出来的对象有名字有年龄,无学号,无年级
constructor(name: String, age: Int) : this("", 0, name, age)
//这个次构造函数创建出来的对象,名字,年龄,学号,年级均不清楚
constructor() : this("", 0)
}
下面是使用次构造函数创建的两个学生对象
//知道名字和年龄的学生对象
val studentOne = Student("沉香",18)
//什么信息都不清楚的学生对象
val studentTwo = Student()
特殊情况,Kotlin允许有次构造函数但没有主构造函数的类
类代码如下:
class Teacher : Person {
constructor(name: String,age: Int):super(name,age)
}
所以当类没有主构造函数时,类的定义是不需要带括号()
3.3 接口
Kotlin接口和Java中的接口是一样
创建一个接口
interface Study {
fun readBooks()
fun doHomeWork()
}
在Student和Teacher中实现Study接口
class Student(val id: String, val grade: Int, name: String, age: Int) : Person(name, age), Study {
init {
println("该学生的学号是:$id")
println("该学生的年级是:$grade" + "年级")
}
//这个次构造函数创建出来的对象有名字有年龄,无学号,无年级
constructor(name: String, age: Int) : this("", 0, name, age)
//这个次构造函数创建出来的对象,名字,年龄,学号,年级均不清楚
constructor() : this("", 0)
override fun readBooks() {
println("学生$name 正在读书。")
}
override fun doHomeWork() {
println("学生$name 正在做家务。")
}
}
class Teacher : Person, Study {
constructor(name: String,age: Int):super(name,age)
override fun readBooks() {
println("教师$name 正在读书。")
}
override fun doHomeWork() {
println("教师$name 正在做家务。")
}
}
使用接口实现面向对象的多态特性,定义一个参数为Study接口的方法
fun doAction(study: Study){
study.readBooks()
study.doHomeWork()
}
在main方法中创建一个Student对象和一个Teacher对象,将这两个对象分别传入doAction方法中,并执行代码
val studentOne = Student("哪吒",18)
val teacher = Teacher("太乙真人",1000)
doAction(studentOne)
doAction(teacher)
运行结果是:
学生哪吒 正在读书。
学生哪吒 正在做家务。
教师太乙真人 正在读书。
教师太乙真人 正在做家务。