《第一行代码》第三版第二章(快速入门kotlin)

2.1 kotlin 语言简介

kotlin继承了java的全部财产后,语法更加简洁,也更加高级,语言更加安全。学习该语言需要有一定的编程基础。

2.2 如何运行kotlin代码

三种方法:
1.下载 intellij IDEA
2.在线编程(外国网站,打不开)
3.Android Studio

2.3 编程之本:变量和函数

1. 变量

不可变变量:val(value)
可变变量:var(variable)
kotlin 拥有出色的类型推导机制,可以不声明类型
当然也可以自己声明,这时kotlin不会运行类型推导机制
如: val a = 10
val a:Int = 10

Kotlin完全抛弃了Java中的基本数据类型,全部使用了对象数据类型。在Java中int是 整型变量的关键字,而在Kotlin中Int变成了一个类,它拥有自己的方法和继承结构。
在这里插入图片描述
优先使用val,后考虑var

2. 函数

在这里插入图片描述
良好的编程习惯:函数名要有一定的意义
在这里插入图片描述
课本中例子:
fun largerNumber(num1: Int ,num2: Int) = max (num1,num2)

3. 语法糖

见简书:https://www.jianshu.com/p/277ada6d3c3c

2.4 程序的逻辑控制

1. if条件语句

下面是if条件语句在kotlin的简化过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可见kotlin 有Java的额外功能返回值,并且语法糖的作用不小

2. when条件语句

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里如果else结尾的 when语句会报错

总结:when语句可以代替多个if,有点像switch,并且它还可以进行类型匹配,需要注意的是要以else结尾

3. 循环语句

  1. while循环
    while (条件表达式) {
    循环语句
    }
  2. for in 循环
    关键字简介:
    . . (连续的两个点):表示双端闭区间
    until :表示左闭右开区间(a <= x <b)
    step :跳过某个元素
    downTo :降序区间(双端闭区间)
    在这里插入图片描述

2.5面向对象编程

在网上找了一个比较能让自己理解的例子区分面向对象和面向过程,如下:

有一天你想吃鱼香肉丝了,怎么办呢?你有两个选择

1、自己买材料,肉,鱼香肉丝调料,蒜苔,胡萝卜等等然后切菜切肉,开炒,盛到盘子里。

2、去饭店,张开嘴:老板!来一份鱼香肉丝!

看出来区别了吗?这就是1是面向过程,2是面向对象。

面向对象有什么优势呢?首先你不需要知道鱼香肉丝是怎么做的,降低了耦合性。如果你突然不想吃鱼香肉丝了,想吃洛阳白菜,对于1你可能不太容易了,还需要重新买菜,买调料什么的。对于2,太容易了,大喊:老板!那个鱼香肉丝换成洛阳白菜吧,提高了可维护性。总的来说就是降低耦合,提高维护性!

面向过程是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。

面向对象是模型化的,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。

面向对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们我们使用的就是面向对象了。

面向过程:

优点:性能比面向对象好,因为类调用时需要实例化,开销比较大,比较消耗资源。
缺点:不易维护、不易复用、不易扩展.

面向对象
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 .
缺点:性能比面向过程差

作者:猪_队友
链接:https://www.jianshu.com/p/7a5b0043b035
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.类与对象

类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。
上面是官方的语言,这边举例用通俗得语言解释一下类。
如:我们人类是一个,那么“人”这个类就是抽象的,而真实存在的应该是某个人(具体指明某个人,这个便是是实例化的时候需要做的,实例化后就是对象了)当然这个对象就具有人类所具有的年龄、外貌、能力等属性。

代码如下

package com.example.helloworld

class Person {		//创建人  这个类
    var name = " "			//“人”类的属性
    var age = 0				//“人”类的属性
    fun eat (){				//“人”类的属性
        println(name + "is eating. He is "+ age + "years old.")
    }
}
fun main() {
    val myfriend = Person()		// 这里就是实例化操作 
    myfriend.age = 19			//以下是对对象进行赋值
    myfriend.name = "lihua"
    myfriend.eat()

}

以上仅个人理解,有错误希望指出,见谅!

2. 继承与构造函数

(1)继承

继承:通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
简单来说就是子类继承父类的特性,扩展父类的功能。
代码如下:在这里插入图片描述
这里要注意的是:

  1. kotlin在设计之初,默认所有非抽象类都是不可以继承的。(这就是为什么用open)
  2. Peron后有()。
(2)主构造函数

构造函数(主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值):
主构造函数(没有函数体)
如果需要编写一些逻辑需要用到 init
例如:

class Student(val sno: String,val grade : Int ) : Person(){
    init {
        println("suo is " + sno)
        println("grade is " +grade)
    }
}

构造函数写法演变:

class Person constructor(username: String, age: Int){
    private val username: String
    private var age: Int

    init{
        this.username = username
        this.age = age
    }
}
----->
class Person (username: String, age: Int){
    private val username: String
    private var age: Int

    init{
        this.username = username
        this.age = age
    }
}
----->
class Person(username: String, age: Int){
    private val username: String = username
    private var age: Int = age
}
----->
class Person(private val username: String, private var age: Int){}
----->
class Person(private val username: String, private var age: Int)



根据继承的特性规定,子类的构造函数必须调用父类的构造函数
我们需要在子类的主调函数上加上父类主调函数的参数,最后传入父类
例如

class Student(val sno: String,val grade : Int,name : String,age : Int ) : Person(name,age){
    init {
        println("suo is " + sno)
        println("suo is " +grade)
    }
}

open class  Person(val name :String,val age : Int){
    fun eat (){
        println(name + "is eating. He is "+ age + "years old.")
    }
}

需要注意 子类中定义的name 和 age 没有 val/var 这是避免与父类中的字段造成冲突

(3)次构造函数

次构造函数通过constructor关键字来定义,都必须调用主构造函数(包括间接调用)
代码如下:
在这里插入图片描述
箭头表示:
第二个次构造函数调用第一个次构造函数(间接调用)
第一个次构造函数调用主构造函数
在这里插入图片描述
因此有三种方式对Student类进行实例化,如下:

val student1 = Student()
    val student2 = Student("jack",19)
    val student3 = Student("a123",5,"jack",19)

kotlin中允许只有次构造函数,无主构造函数
此时次构造函数直接调用父类的构造函数 关键字 super,并且子类:后少去(),如下:

class Student : Person{
    constructor(name : String,age: Int):super(name,age){
    }
}

3. 接口

接口有点类似类,但是又有差别,类的抽象是一般化的,而接口就是特殊化,(即java的类与接口)
下面直接给出例子:

interface Study {
    fun readBooks()
    fun doHomework()
}

class Student(name: String,age: Int) : Person(name,age),Study{
    override fun readBooks() {
        println(name + "is reading book")
    }
    override fun doHomework() {
        println(name + "is doing homework")
    }
}

多态(面向接口编程) 如下:

fun main() {
    val student = Student("jack",19)
    doStudy(student)
    
}
fun doStudy(study: Study){
    study.readBooks()
    study.readBooks()
}

这里的Study是个类型(个人理解为能做学习这件事的类型)
所以Student这个类就是能做学习这个事的
所以就是 实例化一个 student 将这个实例传进doStudy()中

kotlin中允许接口中定义的函数进行默认实现。
接口中支持抽象属性
Kotlin接口中的属性,同方法一样,若没有指定默认行为,则在实现该接口的类中必须对该属性进行初始化。

可见修饰符
在这里插入图片描述

4.数据类与单例类

在这里插入图片描述
在这里插入图片描述

2.6 Lambda编程

1. 集合的创建与遍历

(与Java基本一样)
List Set Map 集合
List如下:

val list1 = listOf<String>("apple","banana","orange","pear","grape")
    for(fruit1 in list1)
        println(fruit1)
    val list2 = mutableListOf<String>("apple","banana","orange","pear","grape")
    list2.add("watermelon")
    for(fruit2 in list2 )
        println(fruit2)

详细请看:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/array-list-of.html
Set集合 和List 集合相似,set无法保证有序

Map集合如下:

/* val map = HashMap<String,Int>()
    map["apple"] = 1
    map["banana"] = 2
    map["orange"] = 3
    map["peat"] = 4
    map["grape"] = 5 */
    val map = mapOf("apple" to  1,"banana" to 2,"orange" to 3)
    for ((fruit,number) in map){	//这里fruit和number的用法注意一下
        println("fruit is "+ fruit +",number is " + number)

2.集合的函数式API

(1)lambda表达式

在这里插入图片描述
举例:
在这里插入图片描述
这里用map函数映射,然后一个元素进去lambda 出来一个新的元素 最后map合并成一个新的集合
在这里插入图片描述

(2)常用的函数API:

map:映射;
filter:过滤;需要注意的是,在filter与其他函数共同使用时,先用filter那样可以提高效率
,如:

val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
    val newlist = list.filter { it.length <= 5 }
        .map{it.toUpperCase()}
    for (fruit in newlist) {
        println(fruit)
    }

any:任何一个满足条件,返回值boolean
all:所有都满足条件,返回值boolean
如下:

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
    val any = list.any{it.length <= 5}
    val all = list.all { it.length <= 5 }
    println("any is "+any +",all is "+all)

3. java函数式API的使用

在这里插入图片描述


    java 版本创建并执行一个子线程
    new Thread(new Runnable(){
    @Override
    public void run(){
        System.out.println("Thread is running");
     }
     }).start()
     
     kotlin 未简化版
     Thread (Object : Runnable {
        override fun run(){
            println("Thread is running")
            }
      }).strat()
    
  kotlin简化版
    Thread(Runnable {
        println("Thread is running")
    }).start()

2.7 空指针检查

1. 可空类型系统

在这里插入图片描述
在这里插入图片描述

2. 判空辅助工具

(1)?. : 对象不为空时继续调用相应的方法
fun main() {
    doStudy(null)
}

fun doStudy(study: Study?){

        study?.readBooks()
        study?.readBooks()

}

学习一个 ?: 常用的方法: 表示左边不空则返回左边,否则返回右边的表达式结果
?:表示对象可以为空

val c = a ?: b
(2)!! : 意思是这个参数如果为空,就抛出异常

如下:

    var content : String? = "hello"
fun main() {
    if (content != null){
        printupperCase()
    }
        
}
fun printupperCase(){
    val upperCase = content!!.toUpperCase()
    println(upperCase)
}
(3)let:将原始对象作为参数传递到lambda表达式中
fun doStudy(study: Study?) {
    study?.let { stu ->
        stu.readBooks()
        stu.doHomework()
    }
}

结合lambda表达式的参数列表中只有一个参数时,可以不用声明参数名化简

fun doStudy(study: Study?) {
    study?.let {
        it.readBooks()
        it.doHomework()
    }
}

而且 let 可以处理全局变量,而if不行!!

2.8 kotlin中的小魔术

1. 字符串内嵌表达式

${ } : 当表达式中只有一个变量的时候,还可以省去大括号。

fun main() {
    val brand = "samsung"
    val price = 1299.99
    println("Cellphone(brand=$brand,price=$price)")

2. 函数的参数默认值

在这里插入图片描述
kotlin还有一个神奇的机制:键值对的方式传参数,如下:

fun printParams(num: Int = 100, str: String) {
    println("num is $num , str is $str")
}
fun main() {
   printParams(str = "world")
}

这种方式会大程度的替代次构造函数的作用!!

以下是一些个人在学习过程中的经验或者说犯的错误

  1. Android studio 的字体太小,容易把标点打错或者看错。(如冒号打成分号)点击解决
  2. 这是我遇到的一个错误,当时 } 这个在很下面,我集中在main函数上就没有去考虑下面的,然后点击了一下划绿线的地方就跳到了这个错误的地方。
    在这里插入图片描述
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值