Kotlin 文件关键字
最后修改于 2025 年 4 月 19 日
Kotlin 的 file 关键字用于指定顶级声明的可见性修饰符。它控制对同一文件内声明的访问。本教程通过实际例子探讨了文件级可见性。
基本定义
Kotlin 中的 file 可见性修饰符使声明仅在同一源文件中可见。对于顶级声明,它比 internal 更严格,但比 private 宽松。
基本的文件私有可见性
file 关键字将可见性限制为当前文件。这对于不应在外部公开的辅助函数或类很有用。
package com.zetcode.utils
file fun calculateSquare(x: Int): Int {
return x * x
}
fun publicCalculateCube(x: Int): Int {
return x * x * x
}
fun main() {
println(calculateSquare(5)) // Accessible: 25
println(publicCalculateCube(3)) // Accessible: 27
}
在这里,calculateSquare 是文件私有的,只能在 Utils.kt 中使用。publicCalculateCube 可从其他文件访问。两者都可以在同一文件中的 main 函数中访问。
文件私有类
类也可以使用 file 修饰符标记为文件私有。这对于不应泄露到文件外部的实现细节很有用。
package com.zetcode.db
file class DatabaseConnection(private val url: String) {
fun connect() = println("Connected to $url")
}
fun createConnection(): DatabaseConnection {
return DatabaseConnection("jdbc:mysql:///mydb")
}
fun main() {
val conn = createConnection()
conn.connect() // Works within same file
}
DatabaseConnection 类仅在 Database.kt 中可见。createConnection 函数可以返回它,因为它们在同一个文件中。外部文件无法直接创建 DatabaseConnection 实例。
文件私有属性
顶级属性可以是文件私有的,以便在文件内共享状态,同时将其对其他文件隐藏。这对于模块级常量很有用。
package com.zetcode.config
file const val MAX_RETRIES = 3
const val TIMEOUT = 5000L
fun shouldRetry(attempt: Int): Boolean {
return attempt < MAX_RETRIES
}
fun main() {
println(shouldRetry(2)) // true
println("Timeout: $TIMEOUT") // 5000
}
MAX_RETRIES 是文件私有的,而 TIMEOUT 是 public 的。两者都可以在 Config.kt 中访问,但只有 TIMEOUT 可以从其他文件访问。这控制了哪些实现细节被公开。
文件私有扩展函数
扩展函数可以是文件私有的,以限制其范围。这可以防止用仅在本地需要的扩展污染全局命名空间。
package com.zetcode.utils
file fun String.encrypt(): String {
return this.reversed()
}
fun String.publicEncrypt(): String {
return encrypt() // Can call file-private function
}
fun main() {
val secret = "password".encrypt() // Works
println(secret) // Output: drowssap
}
encrypt 扩展仅在 StringUtils.kt 中可用。publicEncrypt 可以在内部使用它。这种模式可以防止辅助扩展对其他文件可见,同时仍然可以在内部重复使用。
文件私有接口
接口可以是文件私有的,以将其实现限制为当前文件。这对于组件之间的内部约定很有用。
package com.zetcode.logging
file interface Logger {
fun log(message: String)
}
class ConsoleLogger : Logger {
override fun log(message: String) {
println("[LOG] $message")
}
}
fun createLogger(): Logger {
return ConsoleLogger()
}
fun main() {
val logger = createLogger()
logger.log("Test message") // [LOG] Test message
}
Logger 接口仅在 Logger.kt 中可见。外部文件可以使用 createLogger 但不能直接实现 Logger。这强制执行创建记录器的受控方式。
文件私有伴生对象
伴生对象成员可以是文件私有的,以便在类方法之间共享实现细节,同时将其对其他文件隐藏。
package com.zetcode.utils
class IdGenerator {
companion object {
file var counter = 0
file fun nextId() = ++counter
}
fun generate(): Int {
return nextId() // Can access file-private members
}
}
fun main() {
val gen = IdGenerator()
println(gen.generate()) // 1
println(gen.generate()) // 2
}
counter 和 nextId 是文件私有的,但可被所有 IdGenerator 方法访问。这维护了状态,同时防止外部修改。每次调用 generate 都会增加计数器。
文件私有和内部可见性
当比较 file 和 internal 可见性时,file 更严格。internal 使声明对整个模块可见。
package com.zetcode.visibility
file val filePrivate = "File private"
internal val moduleVisible = "Module visible"
fun printValues() {
println(filePrivate) // Accessible
println(moduleVisible) // Accessible
}
fun main() {
printValues()
}
filePrivate 仅在 Visibility.kt 中可见,而 moduleVisible 可以从同一模块中的任何文件访问。两者都可以在声明它们的文件中访问。
文件私有声明的最佳实践
- 隐藏实现细节:对不应在文件外部公开的辅助程序使用文件私有。
- 减少命名空间污染:使特定于文件的扩展和实用程序保持文件私有。
- 谨慎地共享状态:使用文件私有属性来表示不应在外部修改的文件级状态。
- 记录文件私有 API:即使它们不是 public 的,也要为维护人员记录它们。
- 考虑备选方案:对于真正私有的声明,请在类或对象中使用
private。
来源
本教程深入探讨了 Kotlin 的 file 可见性修饰符。我们探讨了各种用例,包括函数、类、属性和接口。正确使用文件私有可见性有助于创建干净、模块化的代码,并对实现细节进行良好控制的访问。
作者
列出 所有 Kotlin 教程。