Kotlin包名,函数
主要参考:https://www.gitbook.com/book/huanglizhuo/kotlin-in-chinese/details 这本书,大神们也可也自行前往阅读,这篇文章主要是对一些不起眼的知识点进行了梳理和总结,让大家对kotlin的了解更进一步。有很多人说资料太少了,这里我拿了鸿洋大神整理出来的一些别人分享的东西,地址连接http://blog.csdn.net/sinat_36668731/article/details/72529986,在文章的下面干货集锦。
1.定义包名
在源文件的开头定义包名:
package foo.bar
import java.util.*
fun bza() {}
class Goo {}
//...
kotlin源文件不需要和文件夹路径一致:源文件可以放在任何文件目录。
源文件的所有内容(比如类和函数)都被包声明包括。因此在上面的例子中, bza() 的全名应该是 foo.bar.bza ,Goo 的全名是 foo.bar.Goo。
如果没有指定包名,那这个文件的内容就从属于默认 “default” 包。
默认导入的包名:
- kotlin.
- kotlin.annotation.
- kotlin.collections.
- kotlin.comparisons. (since 1.1)
- kotlin.io.
- kotlin.ranges.
- kotlin.sequences.
- kotlin.text.
一些增强包会根据平台来决定是否默认导入:
- JVM
- java.lang.
- kotlin.jvm.
- JS:
- kotlin.js.*
Imports
除了模块中默认导入的包,每个文件都可以有它自己的导入指令。导入语法的声明在grammar中描述。
我们可以导入一个单独的名字,比如下面这样:
import foo.Bar // Bar 现在可以不用条件就可以使用
或者范围内的所有可用的内容 (包,类,对象,等等):
import foo.*/ /foo 中的所有都可以使用
如果命名有冲突,我们可以使用 as 关键字局部重命名解决冲突
import foo.Bar // Bar 可以使用
import bar.Bar as bBar // bBar 代表 'bar.Bar'
import关键字不局限于导入类;您也可以使用它来导入其他声明:
- 顶级函数与属性
- 在对象声明中声明的函数和属性
- 枚举常量
可见性和包嵌套
如果最顶的声明标注为 private , 那么它是自己对应包私有 。如果包内有私有的属性或方法,那它对所有的子包是可见的。
注意包外的的成员是默认不导入的,比如在导入 foo.bar 后我们不能获得 foo 的成员,这个和java都是一样的
函数定义
//Int 为参数,返回值也是Int类型,和swift一样
fun sum(a: Int , b: Int) : Int{
return a + b
}
fun main(args: Array<String>) {
print("sum of 3 and 5 is ")
println(sum(3, 5))
}
该函数只有一个表达式函数体以及一个自推导型的返回值:
fun sum(a: Int, b: Int) = a + b //kotlin方法会根据表达式自动识别出返回值类型
fun main(args: Array<String>) {
println("sum of 19 and 23 is ${sum(19, 23)}")
}
返回一个没有意义的值(类似于java中的void ):
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
fun main(args: Array<String>) {
printSum(-1, 8)
}
Unit 的返回类型可以省略:
fun printSum(a: Int, b: Int) {
println("sum of $a and $b is ${a + b}")
}
fun main(args: Array<String>) {
printSum(-1, 8)
}
函数参数可以设置默认值,当参数被忽略时会使用默认值。这样相比其他语言可以减少重载, 默认值可以通过在type类型后使用=号进行赋值
// 这里off、len都使用了默认值,
fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size() ) {
...
}
命名参数
在调用函数时可以参数命名。这对于那种有大量参数的函数是很方便的.
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 = ' ')
注意:命名参数语法不能够被用于调用Java函数中,因为Java的字节码不能确保方法参数命名的不变性
单表达式函数
当函数只返回单个表达式时,大括号可以省略并在 = 后面定义函数体
fun double(x: Int): Int = x*2
在编译器可以推断出返回值类型的时候,返回值的类型可以省略:
fun double(x: Int) = x * 2
变长参数
函数的参数(通常是最后一个参数)可以用 vararg 修饰符进行标记:
fun asList<T>(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts)
result.add(t)
return result
}
标记后,允许给函数传递可变长度的参数:
val list = asList(1, 2, 3)
lambda(匿名函数)
// 测试
fun main(args: Array<String>) {
val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
println(sumLambda(1,2)) // 输出 3
}
函数范围
每个函数都有自己的作用域,也就是所谓的函数范围。Kotlin 中可以在文件顶级声明函数,这就意味者你不用像在Java,C#或是Scala一样创建一个类来持有函数。除了顶级函数,Kotlin 函数可以声明为局部的,作为成员函数或扩展函数。
局部函数
Kotlin 支持局部函数,比如在一个函数包含另一函数。
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])
}
局部函数甚至可以返回到外部函数
fun reachable(from: Vertex, to: Vertex): Boolean {
val visited = HashSet<Vertex>()
fun dfs(current: Vertex) {
if (current == to) return@reachable true
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v)
}
dfs(from)
return false
}
局部函数和java思路是一样,都是局部函数可以持外部函数的引用。
成员函数
成员函数是定义在一个类或对象里边的
class Sample() {
fun foo() { print("Foo") }
}
成员函数可以用 . 的方式调用
Sample.foo()
这个的使用方法也和java一样,只不过对象不是new出来的而已,具体的后面再讲
泛型函数
函数可以有泛型参数,样式是在函数后跟上尖括号。
fun sigletonArray<T>(item: T): Array<T> {
return Array<T>(1, {item})
}
这个思路也是和android一直的
尾递归函数
Kotlin 支持函数式编程的尾递归。这个允许一些算法可以通过循环而不是递归解决问题,从而避免了栈溢出。当函数被标记为 tailrec 时,编译器会优化递归,并用高效迅速的循环代替它。
tailrec fun findFixPoint(x: Double = 1.0): Double
= if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))
这段代码计算的是数学上的余弦不动点。Math.cos 从 1.0 开始不断重复,直到值不变为止,结果是 0.7390851332151607 这段代码和下面的是等效的:
private fun findFixPoint(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if ( x == y ) return y
x = y
}
}
使用 tailrec 修饰符必须在最后一个操作中调用自己。在递归调用代码后面是不允许有其它代码的,并且也不可以在 try/catch/finall 块中进行使用。当前的尾递归只在 JVM 的后端中可以用。
在学习Kotlin中难免会遇到一些不懂的和一些坑,这时候就需要大家相互分享和提点,这里推荐一下Kotlin社区,欢迎大家来交流。
下面附上qq群:302755325