// 函數定義及調用 fun double(x: Int): Int { return 2*x } val result = double(2) // 調用方法 Sample().foo() // create instance of class Sample and call foo // 參數語法 fun powerOf(number: Int, exponent: Int) { ... } // 缺省參數 fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size()) { ... } // 帶缺省參數的方法被覆蓋時不能帶缺省參數 open class A { open fun foo(i: Int = 10) { ... } } class B : A() { override fun foo(i: Int) { ... } // no default value allowed } // 缺省參數以後還能夠有不帶缺省值的參數 fun foo(bar: Int = 0, baz: Int) { /* ... */ } foo(baz = 1) // The default value bar = 0 is used // 缺省參數以後還能夠有 lambda 參數 fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /* ... */ } foo(1) { println("hello") } // Uses the default value baz = 1 foo { println("hello") } // Uses both default values bar = 0 and baz = 1 // 具名參數 fun reformat(str: String, normalizeCase: Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ' ') { ... } reformat(str) reformat(str, true, true, false, '_') reformat(str, normalizeCase = true, upperCaseFirstLetter = true, divideByCamelHumps = false, wordSeparator = '_' ) reformat(str, wordSeparator = '_') // 展開(spread)運算符 fun foo(vararg strings: String) { /* ... */ } foo(strings = *arrayOf("a", "b", "c")) // 返回類型爲Unit的函數 fun printHello(name: String?): Unit { if (name != null) println("Hello ${name}") else println("Hi there!") // `return Unit` or `return` is optional } fun printHello(name: String?) { ... } // 表達式函數 fun double(x: Int): Int = x * 2 fun double(x: Int) = x * 2 // varargs fun <T> asList(vararg ts: T): List<T> { val result = ArrayList<T>() for (t in ts) // ts is an Array result.add(t) return result } val list = asList(1, 2, 3) val a = arrayOf(1, 2, 3) val list = asList(-1, 0, *a, 4) // 擴展函數的中綴表示法 infix fun Int.shl(x: Int): Int { // ... } // calling the function using the infix notation 1 shl 2 // is the same as 1.shl(2) // 成員函數的中綴表示法 class MyStringCollection { infix fun add(s: String) { /* ... */ } fun build() { this add "abc" // Correct add("abc") // Correct add "abc" // Incorrect: the receiver must be specified } } // 局部函數 fun dfs(graph: Graph) { fun dfs(current: Vertex, visited: Set<Vertex>) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v, visited) } dfs(graph.vertices[0], HashSet()) } fun dfs(graph: Graph) { val visited = HashSet<Vertex>() fun dfs(current: Vertex) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v) } dfs(graph.vertices[0]) } // 成員函數 class Sample() { fun foo() { print("Foo") } } Sample().foo() // creates instance of class Sample and calls foo // 泛型函數 fun <T> singletonList(item: T): List<T> { // ... }
高階函數:將函數做爲參數或返回值的函數。
lambda表達式的特色html
// 高階函數 fun <T> lock(lock: Lock, body: () -> T): T { lock.lock() try { return body() } finally { lock.unlock() } } // 使用函數引用(function references)將函數做爲參數傳給函數 fun toBeSynchronized() = sharedResource.operation() val result = lock(lock, ::toBeSynchronized) // 使用lambda表達式 val result = lock(lock, { sharedResource.operation() }) // lambda表達式是最後一個參數時,括弧能夠省略 lock (lock) { sharedResource.operation() } // 高階函數map fun <T, R> List<T>.map(transform: (T) -> R): List<R> { val result = arrayListOf<R>() for (item in this) result.add(transform(item)) return result } val doubled = ints.map { value -> value * 2 } // 只有一個參數時可使用隱式參數it ints.map { it * 2 } // LINQ風格的代碼 strings.filter { it.length == 5 }.sortBy { it }.map { it.toUpperCase() } // 不須要使用的參數能夠用下劃線表示 map.forEach { _, value -> println("$value!") } // lambda表達式語法 val sum = { x: Int, y: Int -> x + y } val sum: (Int, Int) -> Int = { x, y -> x + y } ints.filter { it > 0 } // this literal is of type '(it: Int) -> Boolean' // lambda表達式隱式返回最後一個表達式的值 // 兩段代碼效果相同 ints.filter { val shouldFilter = it > 0 shouldFilter } ints.filter { val shouldFilter = it > 0 return@filter shouldFilter } // 匿名函數 fun(x: Int, y: Int): Int = x + y fun(x: Int, y: Int): Int { return x + y } // 使用匿名函數 // 參數類型可省略 ints.filter(fun(item) = item > 0) // 閉包(Closures) var sum = 0 ints.filter { it > 0 }.forEach { sum += it } print(sum) // 帶 receiver(隱含調用方)的函數字面量 sum : Int.(other: Int) -> Int 1.sum(2) val sum = fun Int.(other: Int): Int = this + other // String.(Int) -> Boolean 與 (String, Int) -> Boolean 相互兼容 val represents: String.(Int) -> Boolean = { other -> toIntOrNull() == other } println("123".represents(123)) // true fun testOperation(op: (String, Int) -> Boolean, a: String, b: Int, c: Boolean) = assert(op(a, b) == c) testOperation(represents, "100", 100, true) // OK // 經過上下文推導 receiver class HTML { fun body() { ... } } fun html(init: HTML.() -> Unit): HTML { val html = HTML() // create the receiver object html.init() // pass the receiver object to the lambda return html } html { // lambda with receiver begins here body() // calling a method on the receiver object }