Kotlin 全面学习之路 (六) -- 对 Top-level 的理解

在描述 Kotlin 中的 Top-level (顶级声明) 之前,我们先熟悉一下 Kotlin 中文件的概念。理解了 Kotlin 文件的概念,对于理解 Top-level 的相关有所帮助。

1. Kotlin 文件

在 Kotlin 项目目录中, 文件是以 .kt 为后缀名,表示这是一个 Kotlin 文件。

1.1 命名规范

对文件的命名最好符合编码规范,方便自己、方便他人。

  1. 当 Kotlin 文件包含单个类,那么文件的名字应与类名相同,并以 .kt 为后缀。
  2. 当Kotlin 文件保包含多个类或者只包含顶级声明(top-level),那么选择一个可以描述文件内容的名称作为该文件的名字。

总的来说,命名最好可以描述该文件内容。

1.2 源文件组织

鼓励多个声明(类、顶级函数或者属性)放在同一个 Kotlin 源文件中, 只要这些声
明在语义上彼此紧密关联并且文件保持合理大小 (不超过几百行)。

特别是在为类定义与类的所有客户都相关的扩展函数时, 请将它们放在与类自身定
义相同的地方。而在定义仅对指定客户有意义的扩展函数时,请将它们放在紧挨该
客户代码之后。不要只是为了保存 “类的所有扩展函数”而创建文件。这段话的意思就是告诉我们不要随意新建 Kotlin 文件,这样保证项目的大小不会急速扩大。

2. Top-level

首先需要声明的是 Top-level 是在 Kotlin 中有的概念,在 Java 中是不存在这样的概念的。

2.1 什么是 Top-level

在 Java 中,类是所有的属性、动作的根基点,即一切的声明都依托于类,如下所示

class People{
  private int age;
  private String name;

  public void setName(String name){
    this.name = name
  }
  .....
}

很明显,所有的字段和方法必须存在于一个类中。

而在 Kotlin 中这一规则不复存在,属性和方法可以完全 脱离于类 而单独的声明。

People.kt 文件具体内容如下:

@file:JvmName("KK")
package unitTwo

//top-level 接口
interface Human {
    fun sex(): String
    fun country(): String
}

//top-level 类
class ChineseMan(var sex: String, var country: String) : Human {
    override fun sex() = sex

    override fun country() = country
}

//top-level 属性
val people = ChineseMan("man", "China")

//top-level 方法
fun main(args: Array<String>) {
    println("${people.sex} --- ${people.country}")
}

执行 main() 方法,打印日志为:man --- China

上面 Kotin 文件的正确运行也进一步验证了在 Kotlin 中属性、方法、接口、类等是不依托于类在存在。

2.2 Top-level 的引用

Kotlin 与 Java 毕竟分属于两种不同的语言,其自调和互调的方法肯定是不同的,这些是在日常开发中需要注意的。

2.1 在 Kotlin 中引用 Top-level

2.1.1 同一包文件下,直接调用

TopLevelTest.kt 具体代码如下:

@file:JvmName("KK")
package unitTwo

fun show(name: String) {
    println("name is ${name}")
}

具体在 Main 类中调用 TopLevelTest.kt 文件中的 show 方法

package unitTwo
//import show
object MainObj {
    @JvmStatic
    fun main(args: Array<String>) {
        show("mike")
    }
}

打印日志为:name is mike

当然你也可以将 show 方法通过 impor 的方式引入,不过在同包下可以不写。

注意:不会存在同包下两个文件存在相同的方法或其他相关内容,因为编译器会报出 方法冲突异常 。

2.1.2 不同一包,import 后调用

相同的,我们还是调用 unitTwo/TopLevelTest.kt 文件中的 show 方法,不过现在调用方为位于 unitOne 下的 Main 类:

package unitOne
import unitTwo.show // 首先 import show 方法

object MainObj {
    @JvmStatic
    fun main(args: Array<String>) {
        show("aline")
    }
}

打印日志为:name is aline ,说明我们已经成功完成调用。

注意: 在 Kotlin 中 import 的为 相应文件的方法名 :import unitTwo.show

2.2 在 Java 中引用 Top-level

Kotlin 文件中的 top-level 相关内容再编译成 Jvm 字节码后,其作用就相当于 Java 中的一个个静态内容,
其对应关系为:

top-level 方法 –> 静态方法

不过需要注意的是在 Java 中识别 Kotlin 文件的格式: 文件名Kt , 这样使用在 Java 中才是合法的。

那么如何在 Java 中调用 top-level 相关内容呢?同样分为同包和不同包文件目录。

2.2.1 同一包文件下,通过文件名直接调用
public class Main {

    public static void main(String[] strs){
        TopLevelTestKt.show("John");
    }
}

打印信息为: name is John

2.2.2 不同一包文件下,import 后通过文件名直接调用
package unitTwo;

import unitOne.TestKt;
public class Main {

    public static void main(String[] strs){
        TestKt.show("Mary");
    }
}

打印信息为:name is Mary

当然如果你想自定义 Java 代码调用 Kotlin 文件的名字,可以使用 @file:JvmName("xxx"),如下所示:

TopLevelTest.kt 具体代码如下:

@file:JvmName("KK")
package unitTwo

fun show(name: String) {
    println("name is ${name}")
}

Main.java 具体代码如下:

package unitOne;
import unitTwo.KK;
public class Main {
    public static void main(String[] strs) {
        KK.show("fsdf");// 直接使用 KK 代替相关 JVM 生成的相关类
    }
}

打印日志信息为: name is fsdf ,正确输出。

3. 总结

以上就是在 Kotlin 项目中文件的不同组织方法,以及在 Kotin 中对 Top-level (顶级声明) 的说明和使用.。在使用 Kotlin 语言进行项目开发时熟悉这些规则会避免一些不必要的迷惑。

猜你喜欢

转载自blog.csdn.net/Strange_Monkey/article/details/82666516