介绍Kotlin第一部分(翻译篇)

1、介绍Kotlin

Kotlin是jvm新的开发语言。 谷歌推广Kotlin作为其基于java的Android平台上的第一类语言在五月份。从那之后我就纳闷:这是什么语言?Kotlin已经有好几年了,并且在2016年2月正式在生产系统上运行,语言后的1.0版本,为期一年左右。该语言已经获得很多的赞赏和喜爱。 在这篇文章中我们将涵盖语法等基本构建块,在介绍Kotlin第二部分,我们将接触变量,函数,类,接口和对象。最后,在第三部分,我们来看一看控制流程的几个例子。

1、构建过程

当Kotlin在发展的时候,您的构建过程或多或少和旧的java程序类似。既然您已经熟悉了这些,就没有必要学习新的东西,Gradle/Maven插件:引入Kotlin的构建过程和构建工具。 您可以通过添加Kotlin插件在您的Gradle/Maven中构建脚本。如何做到这一点以及了解更多信息,可以从官方文档Kotlin中找到关于 Maven /Gradle的更多介绍。

2、Kotlin语法

一位伟人曾经说过 talk is cheap, show me the code。 貌似在接触新语言时第一句学到的总是以Hello World开始的。那我们就从这里开始吧。

print("Hello World")

现在,我们已经看到了不同于java的地方。有一些我们熟悉的东西()表示函数调用,但没有分号去结尾,不过看起来也很整齐。好了,下面让我们开始去了解Kotlin吧。

① Kotlin变量

在Kotlin中声明变量有一些不同,我们有关键字valvar,这看起来很相似,但其实有一个重要的区别:

当变量被声明为val时是不可变的(只读),你只能给它分配一次值。变量被声明为var是可变的,可以给它重新分配。

val hello: String = "hello"
val world: String
world = "world"
 
var helloWorld: String = "Hello"
helloWorld = "Hello World"

注意,变量类型如何定义?用冒号分隔。这背后还有一个理由,编译器现在可以决定是否要进行类型推断。这意味着Kotlin比Java有着更强大的类型推断。实际上,你也可以不用声明这些类型编译器也会明白你的意思。

val hell0 = "hi"
val w0rld = "earth"

只有当变量被赋值的时候,该变量的类型才能被推断出来。

② fun

这是什么样的功能呢?由于我们用fun来声明它们,它一定很有趣!哈哈。?

// 无返回值. (也可以这么写 --> fun sayIt (a: String): Unit)
fun sayIt (a: String) { 
    println(a)
}
 
// 有返回值
fun returnIt (returnable: String): String {
    return returnable
}
 
//作为具有推断返回类型和自动返回的单表达式函数
fun returnIt2 (turntable: String) =
    turntable

类型声明遵循相同的模式在这里-它排在后面。在我们的第一个我们不返回任何东西,所以我们可以省略到类型,在这种情况下可以使用Unit。在第二个函数中,我们定义必须返回一个String,使用return语句。最后一个比较令人费解,没有大括号,只是一个等号。这意味着fun是一个表达式,它可以自动返回。

正如你所看到的,在表达式的返回类型上是可选的。可以省略或者留在原位,什么让你更方便(经验法则:长的表达式,把它放在后面。短的表达式,它可以省略)。 Kotlin还引入了可选的命名函数参数的概念。这是很有用的,特别是如果你的函数成长为很多同类型和多种不同参数的时候。

fun optFun(isItFun: Boolean = true, whyIsItFun: String = "Because") = if (isItFun) whyIsItFun else "It's not fun"
 
println(optFun()) // Because
println(optFun(false)) // It’s not fun
println(optFun(whyIsItFun = "It's Summer!")) // It's Summer!

在这个代码块中,我们使用默认值来定义我们的函数参数。当我们这么写的时候,我们可以直接调用该函数的0个、1个或者多个它的参数。

③ 类,接口和对象

与Java一样,Kotlin也具有类和接口。Kotlin团队决定让代码组织更加愉快和语言更加简洁。让我们先了解一下类。

A、类
class SimpleClass
 
// 或者 --> class constructor SimpleClassWithConstructor(val chop: String)
class SimpleClassWithConstructor(val chop: String)

在Kotlin中有很多方式可以创建类。在上面的代码块中给了我们提示:

  • 命名约定以大写字母开头
  • 没有花括号
  • 还有就是在这个例子中没有可见性修改
  • 我们仍然使用class关键字 第二个例子是相似的,但它有一个构造函数。构造函数绑定类的属性(在大多数情况下可以不用关键字constructor,只需要添加类的注解或类的可见性),另一种方式,使得Kotlin更加简洁,当我们实例化这个类时需要给chop赋值。
val lamb = SimpleClassWithConstructor("Hello")

在Kotlin中属性默认是公有的,所以访问该属性的最简单方法:

println(lamb.chop)

这个类不具有任何功能,它只是为我们的数据提供容器。我们可以自定义在里面添加fun类功能。在这种情况下,我们需要使用花括号来包裹我们的声明:

class SimpleClassWithConstructor(val chop: String) {
    fun sayItMate(): String = chop + ", mate"
}

我们可以在这里添加附加的属性,其它类,额外的构造函数或初始化块,我们可以给这些单独分配可见性。

init在Kotlin中做的事情,就是我们通常在Java构造函数中做的事情。如果你想在类中创建一个类,你可以使用inner关键字标记它,以便访问外层类的成员。

class Kenny(val celly: String) {
    lateinit var wheel: CanadianPerson
    val friend: String
 
    init {
        friend = "buddy"
    }
    
    fun initializeWheel (wheeler: String) {
        wheel = CanadianPerson(wheeler)
    }
    
    inner class CanadianPerson(val snipe: String)
 
    // 美元符号使用字符串插值,并使用该属性中定义的toString实现替换$ -prefixed属性名称
    fun sayItCanadianWay(): String = "${wheel.snipe} $celly, $friend"
}
 
val d = Kenny("friend")
d.initializeWheel("I’m not")
print(d.sayItCanadianWay()) // I'm not your friend, buddy

我们通过使用lateinit关键字来告诉编译器,这个属性不为空,即使我们不立即初始化它,这对于不在构造函数中初始化属性很有用。注意,我们的lateinit属性必须是可变的。

init相当于Java中的构造函数块,在那里,我们实例化类时,我们可以执行所需的动作。在这种情况下,我们将一个String赋值给我们的属性。

接下来,我们有一个函数,最终赋值给我们的lateinit属性,实例化一个内部类CanadianPerson,这个内部类只是我们数据的载体。

最后,我们将调用一个函数,这个函数将返回一个String,它使用字符串插值将它们解析并展示出来。

当向类添加其他构造函数时,我们需要调用它们原始的构造函数。

class DoubleTrouble(val str: String){
    constructor(lamb: SimpleClassWithConstructor): this(lamb.chop)
}

我们在类中添加一些简单的功能,除了保存数据什么都不做。

对于这些类型的数据传输对象。Kotlin引入了一个关键字来定义它们:data class。它不同于标准的类,一个data class自动生成equals,hashcode,toString和copy功能。前三个对Java开发者来说是比较熟悉的,第四个是个很好的补充,可以帮助我们从只读数据类创建类似的对象。该copy功能可以这么用:

data class DataClass(val str: String, val num: Int)
val daata = DataClass("Hello", 3)
val peeta = daata.copy(str = "Goodbye")

在这种情况下,我们的peeta包含了num=3和str=“Goodbye”。

我们也可以去获取component数据类对象,这些组件函数通过解构来访问数据类中数据的一种方式。这有利于通过简单的一行调用来获取数据类中的单个属性。

val (str, num) = peeta

有了这个技巧,我们的变量str和num的值分别为"Goodbye"和3。请注意,解构变量的顺序取决于数据类中属性的顺序;这些名字根本不重要。

另外还有两个顶级结构interface和objects。

b、接口

Kotlin中接口与Java中没有什么不同,

interface Sayer {
    val value: String
    fun sayIt(): String
}
 
class SayerClass: Sayer{
    override val value: String = "Hello"
    override fun sayIt(): String = "$value, world"
}
 
println(SayerClass().sayIt()) // Hello, world

如您所见,这与Java非常相似,像Java8一样,Kotlin也可以在接口中提供默认实现,我们可以利用这个特性实现上面一样的效果。

interface Sayer {
    val value: String
    fun sayIt(): String {
        return "$value, world"
    }
}

使用这个我们不必重新实现类中的函数。请注意,override关键字在Kotlin中是强制性的。

c、对象
object SingletonClass{
    fun sayIt(): String = "Hello world"
}
 
class CompaniedClass(val str: String){
    companion object Printer{
        fun sayIt(): String = "Hello world"
    }
}

这是什么呢?你可以使用object关键字创建SingletonClass的单例。

SingletonClass.sayIt() // Hello world

Companied对象是略有不同的,它在一个类中定义,它仍然是一个单例,它可以使用包装类的名称来访问。

CompaniedClass.sayIt() // Hello world

4、控制流程(if,when,for)

a、if

if在Kotlin中的语句或多或少与Java类似,下面我们来看一下它们的不同:

val three = 4
if (three != 3) {
    println("Liar!")
} else{
    println("Good job")
}

这看起来与Java完全相同。但是也略有不同。

val three = 4
val goodOrNot = if(three != 3) {
    "Liar!"
} else{
    "Good job"
}
println(goodOrNot) // Liar!

如果Kotlin语句实际上是表达式,它返回它们块中的最后一个值,

b、when

我们常用的switch-case三元运算符有着同样的命运,它已被Kotlin的when所取代。

when (three) {
    3 -> print("three is three")
    2 -> print("three is two?!?")
    else -> print("I don't know what's going on anymore")
}

正如你所看到的,else替代了default->替换了:字符,关键字break也不再需要,因为when表达式将在第一个为真时停止。这些when表达式有一些有趣的地方,它们可以使用任何类型的表达式进行判断,许多情况下,可以捆绑在一起,而对于数值,可以判断它们的范围。

when (three) {
    3 -> print("three is three")
    1,2 -> print("three is two or one?!?")
    in 4..10 -> print("What? Three can't be between 4 and 10!")
    else -> print("I don't know what's going on anymore")
}

同样的,我们也可以使用when来返回具体值。虽然这看起来有点像if表达式。

val three = 4
val goodOrNot = when {
    three != 3 -> "Liar!"
    else -> "Good job"
}
println(goodOrNot) // Liar!
c、for

for循环相对于Java有挺大的改动。

for (i in 1..10) {
    print(i)
} // 12345678910
 
for (i in 1..10 step 2) {
    print(i)
} // 13579
 
val lst = listOf(1,2,3)
for (i in lst){
    print(i)
} // 123

在第一个例子中我们使用in关键从range中通过..来分配i的值。第二个例子中使用step关键字,表示我们要从这个范围中取其它值。第三个例子循环列表,将listof值打印出来。

总结

以上就是Kotlin语言的基本组成部分,有了这些你就可以使用Kotlin了。希望在看完这篇文章后,你对Kotlin会有自己的看法,在下一章中我们将介绍null safety, lambdas, collections, and types以及Kotlin语言中几个便利的功能

快乐工作,享受编程!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏行者常至

01.python基础知识快速入门

642
来自专栏C/C++基础

C++11 原生字符串

原生字符串(Raw String)指不进行转义“所见即所得”的字符串。很多编程语言早已支持原生字符串,如C#、Python、Shell等。C++作为一门高级程序...

841
来自专栏java架构师

C#泛型详解

我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多...

2726
来自专栏郭耀华‘s Blog

Java命名规范

Java命名规范 定义规范的目的是为了使项目的代码样式统一,使程序有良好的可读性。 包的命名  (全部小写,由域名定义) Java包的名字都是由小写单词组...

3339
来自专栏野路子程序员

【野路子】正则表达式~极速入门图文教程

3088
来自专栏AI研习社

最常见的 35 个 Python 面试题及答案(2018 版)

作为一个 Python 新手,你必须熟悉基础知识。在本文中我们将讨论一些 Python 面试的基础问题和高级问题以及答案,以帮助你完成面试。包括 Python ...

1283
来自专栏机器学习算法与Python学习

python基础-字符串与编码

转载于:廖雪峰的官方网站-python教程 字符编码 我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题。 因为计算机只能处理数字...

44111
来自专栏Python小屋

Python 3.x中reduce()函数完整用法

在Python 3.x中,reduce()不再是内置函数,而是移到了标准库functools中,需要先导入再使用,其官方解释如图所示:

622
来自专栏一个会写诗的程序员的博客

Kotlin 扩展函数 与 JS 的 prototypeKotlin 扩展函数 与 JS 的 prototype

Kotlin的扩展函数功能使得我们可以为现有的类添加新的函数,实现某一具体功能 。 扩展函数是静态解析的,并未对原类添加函数或属性,对类本身没有任何影响。 ...

482
来自专栏老司机的技术博客

人人都能学会的python编程教程8:条件判断与循环

实际的项目中条件判断可以说是使用最多的语法之一了,不管是最简单的判断还是负责的业务逻辑和算法,条件判断都如影随形。

1.2K10

扫码关注云+社区