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

本文深入探讨Kotlin中的顶级声明(Top-level),包括其概念、使用场景及在Kotlin与Java间的互调方法。了解顶级声明如何独立于类存在,掌握在同包与跨包中的调用方式。


在描述 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 语言进行项目开发时熟悉这些规则会避免一些不必要的迷惑。

<think>好的,用户现在问的是关于Kotlin中私有属性名不应该包含下划线的问题,具体是'PERMISSIONS_REQUEST_CODE'这个命名。首先,我需要确认用户的问题背景。他们可能在Android开发中遇到了这个警告,或者是在使用静态代码分析工具如Detekt或Android Studio的检查工具。 用户之前已经询问过“Redundant qualifier name”的问题,现在又提到命名规范,这说明他们可能在优化代码质量,遵循Kotlin的编码规范。Kotlin的官方风格指南确实建议变量名使用驼峰命名法,而不是下划线,尤其是在私有属性中。不过,用户提到的这个变量名全是大写加下划线,看起来像常量,但Kotlin中的常量通常定义在伴生对象中,并使用@JvmStatic注解或者const val,这时候才会用大写命名。如果是私有属性,即使作为常量,也应该使用驼峰式。 接下来,我需要分析用户的具体情况。可能用户将常量错误地定义为私有属性,或者混淆了Kotlin中常量的正确声明方式。比如,如果用户在一个类内部直接使用大写加下划线的命名,而没有放在伴生对象中,并且没有使用const修饰符,这就会触发警告。此外,用户可能没有正确理解常量和普通私有属性的区别,导致命名不符合规范。 然后,我需要考虑用户可能存在的深层需求。他们可能希望代码既符合规范,又能通过静态检查,同时保持可读性。有些开发者习惯在请求码这类变量使用全大写,以便区分,但Kotlin中更推荐驼峰式。需要解释这种命名规范的原因,并提供修改示例,同时说明在什么情况下允许使用下划线(比如伴生对象中的公有常量)。 另外,用户可能对Kotlin的命名约定不太熟悉,尤其是从Java转过来的开发者,因为Java中常量通常用全大写加下划线。所以需要强调Kotlin的不同之处,并指导如何正确声明常量,比如使用伴生对象和const val,以及何时使用大写命名。 最后,确保回答结构清晰,给出问题原因、解决方案、示例代码以及注意事项,帮助用户全面理解问题并正确修改代码。同时,提醒用户使用IDE的快速修复功能,比如Alt+Enter,来自动修正命名问题,提升效率。</think>--- **"Private property name 'PERMISSIONS_REQUEST_CODE' should not contain underscores in the middle or the end"** 是 Kotlin 代码静态检查工具(如 `Detekt` 或 Android Studio 的代码检查)发出的警告,表示私有属性命名不符合 Kotlin 命名规范。以下是详细解析和解决方案: --- ### 问题原因 1. **Kotlin 命名规范**: - Kotlin 官方风格指南建议变量和属性名使用**驼峰式命名法**(CamelCase),例如:`permissionsRequestCode`。 - 下划线(`_`)通常**仅允许在常量命名**中使用(全大写 + 下划线),例如:`const val MAX_RETRY_COUNT = 3`。 2. **私有属性的特殊性**: - 私有属性(`private val`/`private var`)的命名规则与普通变量一致,**不推荐使用下划线**。 - 如果使用下划线,工具会认为这是代码异味(Code Smell)。 --- ### 修复方案 #### 1. 直接修改为驼峰式命名 **问题代码**: ```kotlin private val PERMISSIONS_REQUEST_CODE = 100 // 警告:私有属性包含下划线 ``` **修复后**: ```kotlin private val permissionsRequestCode = 100 // 正确:驼峰式命名 ``` #### 2. 如果是常量,需调整作用域和修饰符 如果该字段是真正的常量(不可变且值在编译时已知),应将其定义为 `companion object` 中的常量: ```kotlin companion object { const val PERMISSIONS_REQUEST_CODE = 100 // 正确:常量允许全大写+下划线 } ``` - 此时 `const val` 是公有静态常量,符合命名规范,不会触发警告。 --- ### 示例场景 #### 错误用法 ```kotlin class MainActivity : AppCompatActivity() { private val PERMISSIONS_REQUEST_CODE = 100 // 警告:私有属性 + 下划线 fun requestPermissions() { requestPermissions( arrayOf(android.Manifest.permission.CAMERA), PERMISSIONS_REQUEST_CODE ) } } ``` #### 正确用法 ```kotlin class MainActivity : AppCompatActivity() { companion object { const val PERMISSIONS_REQUEST_CODE = 100 // 正确:公有常量 } fun requestPermissions() { requestPermissions( arrayOf(android.Manifest.permission.CAMERA), PERMISSIONS_REQUEST_CODE ) } } ``` --- ### 注意事项 1. **常量定义的条件**: - 必须使用 `const val`。 - 值必须是基本类型(`Int`, `String`, `Boolean` 等)或编译时可确定的表达式。 - 通常定义在 `companion object` 或顶层(Top-Level)。 2. **IDE 快速修复**: - 在 Android Studio 中,按 `Alt + Enter` 可自动将下划线命名转换为驼峰式(仅适用于非常量私有属性)。 3. **团队规范优先**: - 如果团队明确允许私有属性使用下划线,可通过静态检查工具(如 Detekt)的配置文件关闭此规则。 --- ### 总结 | 场景 | 正确命名方式 | 错误示例 | |-----------------------|-----------------------------|---------------------------| | 私有非常量属性 | 驼峰式(`permissionsRequestCode`) | `PERMISSIONS_REQUEST_CODE` | | 公有常量 | 全大写+下划线(`PERMISSIONS_REQUEST_CODE`) | `permissionsRequestCode`(语义混淆) | 遵循此规则可提高代码可读性,并与 Kotlin 社区标准保持一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值