JVM · Java虚拟机原理 · JVM上语言·框架· 生态系统Java 8 · Java 9 · Java X · Java 实践指北函数式编程 FP Functional Progamming · Lambda 演算 · Y 组合子

Kotlin 语言极简教程 v0.1 (东海陈光剑)

2018-11-07  本文已影响29人  光剑书架上的书

Kotlin 语言极简教程

v0.1 (东海陈光剑)

简介

是什么

fun main(args: Array<String>){
    println("Hello World!")
}

极简版:

fun main(args: Array<String>) = println("Hello World!")

特性

历史

Speaking at a software conference called QCon London in 2009, he apologised for inventing the null reference:
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

String a  = null;
System.out.println(a.length());

在 Java 里,声明一个 string 类型,赋一个 null 给这个变量。一旦我们要打印这个字符串的时候,会在运行时曝出空指针错误,因为我们在尝试去读一个空值。
* kotlin 写法
* 我们定义一个空值,但是在我们尝试操作它之前,Kotlin 的编译器就告诉了我们问题所在:

val a:String = null

曝出的错误是:我们在尝试着给一个非空类型分配一个 null。在 Kotlin 的类型体系里,有空类型和非空类型。类型系统识别出了 string 是一个非空类型,并且阻止编译器让它以空的状态存在。想要让一个变量为空,我们需要在声明后面加一个 ? 号,同时赋值为 null。

val a: String? = null
println(a.length())

现在,我们修复了这个问题,继续向下:就像在 Java 里一样,我们尝试打印 stirng 的长度,但是我们遇到了跟 Java 一样的问题,这个字符串有可能为空,不过幸好的是:Kotlin 编译器帮助我们发现了这个问题,而不像 Java 那样,在运行时爆出这个错误。

编译器在长度输出的代码前停止了。想要让编译器编译下去,我们得在调用 length 方法的时候考虑到可能为空的情况,要么赋值给这个 string,要么用一个问号在变量名后,这样,代码执行时在读取变量的时候检查它是否为空。

val a: String? = null
println(a?.length())

如果值是空,则会返回空。如果不是空值,就返回真实的值。print 遇到 null 会输出空。

* 智能转换(Smart casts)
* 字符串模板(String templates)
* 主构造函数(Primary constructors)
* 类委托(Class delegation)
* 类型推断(Type inference)
* 单例(Singletons)
* 声明点变量(Declaration-site variance)
* 区间表达式(Range expressions)

现状&未来发展

基本类型

分支循环

if

fun main(args: Array<String>) {
    val name = if (args.isNotEmpty()) {
        args[0]
    } else {
        "World"
    }
    println("Hello, $name!")
}

val name = if (args.isNotEmpty()) args[0] else "Word"

for

enum class Language(val greeting: String) {
    EN("Hello"), ES("Hola"), FR("Bonjour")
}

class Person(var name: String, var lang: Language = Language.EN) {
    fun greet() = println("${lang.greeting}, $name!")
}



fun main(args: Array<String>) {
    val people = listOf(
       Person("Java"),
       Person("Miguel", Language.SP),
       Person("Michelle", Language.FR)
    )

    for (person in people) {
        person.greet()
    }
}

when

when(x) {
  is Int -> print(x + 1)
  is String -> print(x.length + 1)
}

数组集合类

文件 IO

面向对象编程

class Person(var name: String)

fun main(args: Array<String>) {
  val person = Person("Kotlin")
  println("Hello, $name!")
}

数据类

  private String firstName;
  private String lastName;
  private String email;

  public String getFirstName() { return firstName; }
  public String getLastName() { return lastName; }
  public String getEmail() { return email; }

  public void setFirstName(String firstName) { this.firstName = firstName }
  public void setLastName(String lastName) { this.lastName = lastName }
  public void setEmail(String email) { this.email = email }
}
class Customer( var firstName: String ,
 var lastName: String,
 var email: String)

单例

object Logger {
  val tag = "TAG"
  fun d(message: String) {
    Log.d(tag, message)
  }
}

函数式编程

函数类型

Lambda 表达式

高阶函数

// 首先要声明一个函数接口,接受参数类型为 T,返回类型为 R。
public interface Function<T, R> {
  R call(T t);
}

public static <T> List<T> filter(Collection<T> items, Function<T, Boolean> f) {
  final List<T> filtered = new ArrayList<T>();
  for (T item : items) if (f.call(item)) filtered.add(item);
  return filtered;
}

filter(numbers, new Function<Integer, Boolean>() {
  @Override
  public Boolean call(Integer value) {
    return value % 2 == 0;
  }
});
 fun <T> filter(items: Collection<T>, f: (T) -> Boolean): List<T> {
  val filtered = arrayListOf<T>()
  for (item in items) if (f(item)) filtered.add(item)
  return filtered
}

filter(numbers, { value -> value % 2 == 0 })

你可能发现了,我们没有定义任何的函数接口,这是因为在 Kotlin 中,函数也是一种数据类型。看到 f:(T) -> Boolean 这个语句了吗?这就是函数类型作为参数的写法,f 是函数别名,T 是函数接受参数,Boolean 是这个函数的返回值。定义完成后,我们随后就能跟调用其他函数一样调用 f。调用 filter 的时候,我们是用 lambda 表达式来传入过滤函数的,即:

{value -> value % 2 = 0}

由于函数类型参数是可以通过函数声明的签名来推导的,所以其实还有下面的一种写法,大括号内就是第二个参数的函数体:

filter(numbers) {
  it % 2 == 0
}

函数组合示例


package com.light.sword.coursera

val lengthFun = fun(s: String): Int = s.length //lengthFun is a fun variable
val isOddFun = fun(x: Int): Boolean = x % 2 != 0

fun compose(length: (String) -> Int, isOdd: (Int) -> Boolean): (String) -> Boolean {
    return { x -> isOdd(length(x)) }
}

fun main(args: Array<String>) {
    val words = listOf("Hello", "U", "Kotlin", "Java")
    val result = words.filter(compose(lengthFun, isOddFun)) // Use lengthFun directly
    println(result) // [Hello, U]
}

扩展函数

代码实例

fun String.lastChar(): Char = this.get(this.length - 1)

fun main(args: Array<String>) {
    println("Kotlin".lastChar())
}
Kotlin 语言极简教程 v0.1 (东海陈光剑).png
上一篇下一篇

猜你喜欢

热点阅读