Kotlin快速入门:基础语法类与继承集合
Posted 舒泱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin快速入门:基础语法类与继承集合相关的知识,希望对你有一定的参考价值。
参考书籍:
- 《AtomicKotlin》,全英文,读起来慢,但是写得很详细,没有任何语言基础的也能看懂
- 《第一行代码 android 第三版》,第二章,有java基础的看一看就会了
- Kotlin中文文档,很详细,可以当作字典查看,挨着看有点太多了
目录
1 基础语法
1.1 入口函数
kotlin程序的入口是main函数(方法),下面是一个最简单的main函数,程序将从这里开始执行:
fun main() {
println("Hello, world!")
}
fun是声明方法的关键字,println是一个打印语句。main方法也可带输入参数:
fun main(args:Array<String>) {
println("Hello, world!")
}
kotlin每个语句后可以不加分号,如果多个语句写在同一行,需要用分号隔开,但并不推荐将多个语句写在一行。
1.2 输出
输出可以用print()或println()方法,两者的区别是,print()打印后光标不会移动到下一行,println()打印后光标会移动到下一行(多个换行)。
fun main() {
print("Hello,")
print("world!")
// 输出
// Hello,world!
}
fun main() {
println("Hello,")
println("world!")
// 输出
// Hello,
// world!
}
1.3 对象数据类型
kotlin中对象数据类型的首字母是大写的,比如Int,但在java和c++中基本数据类型首字母是小写的。两者的差距并不是首字母大小写这么简单,kotlin中Int变成了一个类,它拥有自己的方法和继承结构。
Double | 双精度浮点型,8字节 |
---|---|
Long | 长整型,8字节 |
Float | 单精度浮点型,4字节 |
Int | 整型,4字节 |
Short | 短整型,2字节 |
Byte | 字节 |
Boolean | 布尔型 |
Char | 字符型 |
1.4 变量和常量
关键字var用于定义变量,关键字val用于定义常量。定义格式如下:
fun main() {
val whole: Int = 11
var fractional: Double = 1.4
val trueOrFalse: Boolean = true
var words: String = "A value"
val character: Char = 'z'
val lines: String = """Triple quotes let
you have many linesin your string"""
}
也可以不写数据类型,编译器会做类型推断:
fun main() {
val whole = 11
var fractional = 1.4
val trueOrFalse = true
var words = "A value"
val character = 'z'
val lines = """Triple quotes let
you have many linesin your string"""
}
1.5 方法(函数)
函数定义基本格式:
fun functionName(p1: Type1, p2: Type2, ...): ReturnType {
lines of code
return result
}
以关键字fun开头,然后是函数名,括号里是入参p1,p2,入参的数据类型是Type1,Type2,括号外是返回值类型ReturnType。
下面是一个加法程序示例:
// 加法程序
fun add(x: Int,y:Int): Int {
return x + y
}
// 主函数
fun main() {
val r = add(5,7)
println(r)
}
当函数没有返回值时,返回值类型写成Unit,Unit可以省略不写,示例如下:
fun sayHello() { // 可以省略Unit
println("Hallo!")
}
fun sayGoodbye(): Unit { // 可以写
println("Auf Wiedersehen!")
}
以上用大括号包围的函数体称为block body。当函数体非常简单,比如只有一个表达式时,可以写成=表达式
的格式,这种称为expression body:
// 这是一个计算3倍x的值的函数,函数体可以写成 =x*3
fun multiplyByThree(x: Int): Int = x * 3
当函数体为expression body时,可以省略返回值类型,编译器会自动推断返回值类型:
// 这是一个计算3倍x的值的函数,省略了返回值类型
fun multiplyByThree(x: Int) = x * 3
kotlin可以给函数设定默认参数值,例如:
fun funOne(int:Int=100,str:String,double: Double=0.7){
println("测试")
}
fun main(){
funOne(str="hh")
}
调用函数时,用这种参数名=参数值的方式传值,传入参数的顺序谁前谁后都无所谓,因为kotlin可以根据参数名将参数准确地匹配上。
1.6 条件语句if
使用方法与C++和Java相同,示例如下:
fun main() {
val n: Int = -11
if (n > 0)
println("正数")
else if (n == 0)
println("0")
else
println("负数")
}
在函数中,当函数体为expression body时,通常可以用if表达式得到返回值,不需要写“return”关键字。(这一点与c++和java不同,它们的if语句是没有返回值的,而kotlin的if语句可以有返回值):
fun checkSign(number: Int): String =
if (number > 0)
"正数" // 不需要写return
else if (number == 0)
"0"
else
"负数"
fun main() {
println(checkSign(-19))
}
1.7 条件语句when
kotlin中的when语句功能类似于c++和java中的switch语句。根据姓名返回得分的函数如下:
fun getScore(name:String)=when(name){
"tom"->90
"lily"->92
"jack"->85
else->0
}
when语句还有一种不带参数的写法,这种写法有时能发挥很强的扩展性。仍是上面这个例子,假设所有名字以tom开头的人得分都是90分,代码如下:
fun getScore(name:String)=when{
name.startsWith("tom")->90
name=="lily"->92
name=="jack"->85
else->0
}
1.8 字符串与$
在字符串中,符号"$"后接变量名时,效果是在字符串中插入变量的值,示例如下:
fun main() {
val answer = 42
println("Found $answer!") // 输出 Found 42!,answer被替换成了它的值
println("printing a $1") // 输出printing a $1,因为1不是变量名,所以不会有特殊的操作
}
在${ }中放入一个表达式时,这个表达式执行后得到的值就会转换成字符串,示例如下:
fun main() {
val condition = true
println("${if (condition) 'a' else 'b'}") // 表达式if (condition) 'a' else 'b'执行后得到'a',转换成字符串"a",并打印出来
}
当想使用一些特殊字符时,可以用反斜杠\\去掉其本身含义,例如:
fun main() {
val str = "value"
println("s = \\"$str\\".") // 反斜杠去掉了两个双引号的 特殊含义,最后输出s = "value".
println("""s = "$s".""") // 也可使用三个双引号,最后输出s = "value".
}
1.9 循环语句while
使用方法与C++和Java相同,示例如下:
var i = 0
while (i < 4) { // 输出....
print(".")
i++
}
1.10 循环语句for与关键字in
使用方法与C++和Java不同。
kotlin在访问一个区间或容器中的内容时,使用关键字in。例如要循环打印区间[1,3]范围内的数:
for (i in 1..3) {
println("$i")
}
// 输出:
// 1
// 2
// 3
区间的表示方法有多种,除了能正向步进外,还能反向步进,也就是例如9~1这样由大到小的区间。此外,除了以1步进外,还能用step指定步进大小,示例如下:
fun main() {
val range1 = 1..5 // 区间[1,5],1 2 3 4 5
val range2 = 1 until 5 // 区间[1,9),用until定义的区间是左闭右开的,1 2 3 4
val range3 = 5 downTo 1 // 反向步进,5 4 3 2 1
val range4 = 0..9 step 2 // 区间[0,9],以2步进,0 2 4 6 8
val range5 = 0 until 10 step 3 // 区间[0,10],以3步进,0 3 6 9
val range6 = 9 downTo 2 step 3 // 反向步进,以3步进,9 6 3
println(range1) // 打印这个区间范围内的所有数
}
此外,除了整数能表示成区间外,字符也能,示例如下:
fun main() {
for (c in 'a'..'z') {
print(c)
}
}
in关键字除了能和for语句一起使用外, 还能用于判断一个值是否属于某个区间,例如:
fun main() {
val i = 35
println(i in 1..100) // 等同于println(0 <= i && i <= 100),输出true
var j:Double= 9.999
println(j in 1.0..10.0) // 输出true,需要注意的是,浮点数只能使用..表示区间,不能使用util
println("ab" in "aa".."az") // 输出 true
println("ba" in "aa".."az") // 输出 false
}
上面代码中需要注意的是,浮点数只能使用…表示区间,不能使用util。
又例如和if语句一起使用:
fun main() {
if( 't' in "kotlin"){
println("true")
}
if( 'a' !in "kotlin"){
println("true")
}
}
/* 输出:
true
true
*/
1.11 repeat()函数
当要重复一个操作时,也可使用repeat(n)函数,n为重复次数,示例如下:
fun main() {
repeat(2) {
println("hi!")
}
}
/* 输出:
hi!
hi!
*/
2 面向对象编程
2.1 类与对象
定义类的方式与c++类似,假设现在定义一个类表示人,程序实例如下:
class Person {
var name =""
var age=0
fun eat(){
println("$name is eating. She/he is $age years old")
}
}
实例化一个类,并给这个类的数据成员赋值:
fun main(){
val p=Person()
p.name="xiaoWang"
p.age=25
p.eat()
}
2.2 继承
c++和java中,一个类默认能被继承,但kotlin中默认类是不能被继承的,如果一个类能被其他类继承,需要在这个类前加上open关键字,主动告诉编译器这个类可以被继承。仍是上面这个例子,程序示例如下:
open class Person {
var name =""
var age=0
fun eat(){
println("$name is eating. She/he is $age years old")
}
}
使Student类继承于Person类,不同于c++的是,在继承时Person后加上了一对括号:
class Student:Person() {
var id=""
var score=0
fun getScore(){
println("id:$id score:$score")
}
}
2.3 构造函数
kotlin将构造函数分成了两种,主构造函数和次构造函数,一个类只有一个主构造函数,但可以有很多个次构造函数。每个类都默认有一个不带参数的主构造函数,例如前面的Person类,用val p=Person()
实例化。
如果要显式的给Student的主构造函数指明参数,程序示例如下:
class Student(id:String,score:Int):Person() {
var id=""
var score=0
fun getScore(){
println("id:$id score:$score")
}
}
此时要实例化类Student,必须带参数:
val xiaoWang = Student("0303",87)
主构造函数的特点是没有函数体,如果想在主构造函数中写一些代码,可以用init结构体:
class Student(id:String,score:Int):Person() {
init { // 主构造函数的函数体
println("id:$id")
println("score:$score")
}
var id=""
var score=0
fun getScore(){
println("id:$id score:$score")
}
}
和c++、java一样,子类的构造函数必须调用父类的构造函数。kotlin中有主构造函数和次构造函数,子类要调用父类的哪个构造函数,需要在继承时指定。例如class Student(id:String,score:Int):Person()
就调用了Person类的默认构造函数Person()。
次构造函数用关键字constructor来定义:
class Student(id:String, score:Int, name: String, age: Int):Person(name, age) {
constructor(id: String,score: Int) : this("",0,name, age) {
println("id:$id score:$score")
}
constructor():this("",0){
}
var id=""
var score=0
fun getScore(){
println("id:$id score:$score")
}
}
以上代码IDE报错“There’s a cycle in the delegation calls chain“,待解决,还没想明白。
2.4 接口
kotlin中的接口和java几乎是完全一致的。c++允许多继承,而java中是禁止多继承的,一个类最多只能继承于一个父类,但却可以实现多个接口。
这里说一下java中抽象类和接口类的区别:抽象类中除了可以有抽象方法外,还可以有数据成员和普通成员方法,接口也可以有数据成员和方法,但接口中的方法必须都是抽象方法。
这里举的例子是,基类是Person,Study是接口,Student继承于Person和Study:
open class Person() { // 使用open关键字,使该类可以被继承
var name =""
var age=0
fun eat(){
println("$name is eating. She/he is $age years old")
}
}
interface Study { // 使用interface关键字定义接口
fun readBooks() // 接口中的函数没有函数体
fun doHomework(){ // 如果有了函数体,那么函数体中的内容就是这个函数默认的实现,其他类继承这个接口后,不是必须实现这个函数
println("这是doHomework()函数的默认实现")
}
}
class Student(id:String, score:Int):Person() ,Study{
var id=""
var score=0
fun getScore(){
println("id:$id score:$score")
}
override fun readBooks() {
println("read books")
}
// 由于接口中的这个函数有默认实现,所以这里可以选择实现或者不实现这个函数,如果不实现,使用的就是这个函数在接口中的默认实现
override fun doHomework() {
println("do homework")
}
}
2.5 可见修饰符
public | 所有类可见 |
---|---|
private | 当前类可见 |
protected | 当前类、子类可见 |
internal | 同一模块中的类可见 |
2.6 数据类与单例类
创建数据类使用关键字data,创建一个手机数据类的实例如下:
data class Cellphone(val price:Double)
kotlin会自动根据主构造函数中的参数将equals()、hashCoad()、toString()等方法写好,而在java中,通常还需要自己重写这些方法。
kotlin中创建单例类也很方便,不需要自己讲构造函数写成私有然后在写一个getInstance()的方法获取实例,只需要讲class关键字换成object关键字即可:
object Singleton{ // 这就是一个单例类了
}
3 空值检查
c++和java中都可能因为空值产生异常,例如:
public void doStudy(Study study){
study.readBooks();
study.doHomework()
}
上面的代码,如果study是null,就会发生空指针异常。kotlin中任何变量和参数都是默认不为空的,kotlin会在编译时就检查空值,如果程序存在空值的风险,编译就通不过。如下的kotlin代码是安全的:
fun doStudy(study:Study){
study.readBooks()
study.doHomework()
}
fun main(){
val xiaoWang=Student("0303",87)
doStudy(xiaoWang)
}
如果传入空值,IDE会在你编辑代码的时候就提示错误。
3.1 ? 与 ?. 与 ?:
如果一个变量可能为空,需要显式地用符号“?”和“?.”指定,例如:
fun doStudy(study:Study?){ // 类型后加上问号?,表示可以为空
study?.readBooks() // 使用?. ,当对象不为空时正常调用,当对象为空时什么都不做。
study?.doHomework()
}
fun main(){
val n=null
doStudy(null)
}
以上是关于Kotlin快速入门:基础语法类与继承集合的主要内容,如果未能解决你的问题,请参考以下文章