Kotlin学习(二)

变量

在Kotlin语言中使用定义变量时,可以在变量名后用冒号跟上类型,明确指定变量类型,也可以利用编译器帮助类型推导,通过赋予变量值,由编译器自动匹配变量类型。
另外,Kotlin语言推荐在定义变量时使用val关键字创建不可变类型,但并未做强制要求。因此在选择的情况下,如果后期不会对其值重复修改,就不用定义为var了。

初始化

变量需要在使用前被初始化,具体的初始化实际不进行要求。

package introduction


fun main() {

    var a: String = "initial"    //声明了一个可变的变量并且对它进行初始化
    println(a)
    val b: Int = 1     //声明一个不可变的量并且初始化
    val c = 3    //声明不可变的量,未指明类型,编译器推导类型为Int

//    var e: Int
//    println(e)         变量需要初始化
//    Error:(11, 13) Kotlin: Variable 'e' must be initialized

    val d: Int      //声明但未初始化
    if (someCondition()) {    //根据条件初始化
        d = 1
    } else {
        d = 2
    }

    println(d)    //使用时以被初始化

    //因此初始化的时机必须在变量被使用前
}

fun someCondition(): Boolean {

    return (System.currentTimeMillis() % 2.0)  == 0.0
}

空值安全

Kotlin中的变量类型都是不可以为空的,如果一定要将null值赋给变量,那么在原来的类型后面加一个?,将其声明为可空类型,这样,就可以将null值赋给它了。

package introduction

fun main() {

    var neverNull: String = "This can't be null"     //声明非空的字符串变量

//    neverNull = null  //赋空值会报错

    var nullable: String? = "You can keep a null here"   //声明可空的字符串变量

    nullable = null      //赋空值不会发生编译错误

    var inferredNotNull = "The compiler assumes non-null"    //由于字符串已经被初始化,则类型推导认为其不能为空

//    inferredNotNull = null   //空值会报错

    fun strLength(notNull: String): Int {    //函数接受的参数被声明为非空类型
        return notNull.length
    }

    strLength(neverNull)
//    strLength(nullable)     //可空类型不能被接受
    println(describeString(null))
    println(describeString(""))
    println(describeString("apple"))
}

fun describeString(maybeString: String?): String {    //接受可空的字符串
    if (maybeString != null && maybeString.isNotEmpty()) {
        return "String of length is ${maybeString.length}"
    } else {
        return "Empty or null string"
    }
}

一个类的声明包括其类名、头部(指明接受的参数类型、主构造器等)、大括号包括的类体。其中,类头和类体都是可选的,根据需要进行类的定义。以下例子体现了类的一些基本用法:

package introduction

//声明一个类,无任何属性,也没有用户自定义的构造方法,
//Kotlin在这样的情况下分配一个无参的默认构造方法Customer()
class Customer

//声明一个类,含有两个属性,并且这两个属性组成构造方法
class Contact(val id: Int, var email: String)    //

fun main() {

    val customer = Customer()    //创建了一个Customer类的实例,使用默认构造法方法

    val contact = Contact(1, "mary@gmail.com")   //创建Contact类的实例,需要两个参数

    println(contact.id)     //访问属性,相当于get方法
    contact.email = "jane@gmail.com"    //更新可变类型的属性,相当于set方法
}

泛型

泛型可以增加一些封装逻辑的重用性。对应的方法或是类使用一个占位符进行定义,然后可以将其替换成自己想要的数据类型,也增强了所谓通用的思想。

泛型类

泛型类使用如下,MutableStack是一个泛型类,尖括号中的E可以被具体的类型取代,这让我们在设计的时候可以更加关注逻辑,而不需要过于在意具体的类型。

泛型方法

同样地,如果方法对于类型的依赖较小,可以将代码逻辑抽象出来,作为更加通用的泛型方法来使用。

package introduction

class MutableStack<E>(vararg items: E) {    //声明了一个泛型类MutableStack<E>,E称作泛型类型参数,在使用时会赋予其明确的类型

    private val elements = items.toMutableList()

    fun push(element: E) = elements.add(element)

    fun peek(): E = elements.last()

    fun pop(): E = elements.removeAt(elements.size - 1)

    fun isEmpty() = elements.isEmpty()

    fun size() = elements.size

    override fun toString() = "MutableStack(${elements.joinToString()})"
}

fun <E> mutableStackOf(vararg elements: E) = MutableStack(*elements)

fun main() {

    val stack = mutableStackOf(0.62, 3.14, 2.7)   //编译器可以推导泛型类型
    println(stack)
}


继承

在Kotlin中,类是默认为final类型的。因此,如果想要将一个类作为基类,被其他的类所继承,就需要使用到open关键字,这样子类才能出得来。

同样地,Kotlin中,方法也是默认为final的。因此,如果想要在子类中覆写该方法,就需要将方法定义为open的,这样才好拿过去“参考”,不然对方不开源就没法改。覆写方法时,需要使用override关键字指明该方法是后来覆写的。

继承的写法,是使用冒号,格式为:子类:父类(),后面括号的意思其实代表调用无参的默认构造器,可以根据情况修改。

package introduction

open class Dog {       //Kotlin中的类默认为final,如果需要被继承,需要使用open标识符进行修饰
    open fun sayHello() {    //方法默认也为final,如果需要被重写,也要使用open标识符
        println("wow wow!")
    }
}

class Yorkshire: Dog() {    //继承写法,指示调用超类的默认构造方法
    override fun sayHello() {   //覆写方法
        println("wif wif!")
    }
}

open class Tiger(val origin: String) {
    fun sayHello() {
        println("A tiger from $origin says: grrhhh!")
    }
}

class SiberianTiger: Tiger("Siberia")     //含有参数,在继承时传入

open class Lion(val name: String, val origin:String) {
    fun sayHello() {
        println("$name, the lion from $origin says: graoh!")
    }
}

class Asiatic(name: String): Lion(name = name, origin = "India")    //构造方法参数name,用于传值

fun main() {
    val dog: Dog = Yorkshire()
    dog.sayHello()

    val tiger: Tiger = SiberianTiger()
    tiger.sayHello()

    val lion: Lion = Asiatic("Rufo")
    lion.sayHello()
}


官网例子练习
官方详细中文文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值