Kotlin private 关键字
最后修改于 2025 年 4 月 19 日
Kotlin 的访问修饰符控制类、对象和成员的可见性。private
关键字是最严格的修饰符。本教程将通过实际例子深入探讨 private
关键字。
基本定义
Kotlin 中的 private
关键字将可见性限制为声明作用域。私有成员只能在同一类或文件中访问。这通过隐藏实现细节来促进封装。
私有属性
私有属性只能在其声明的类中访问。这可以防止外部代码直接修改内部状态。
package com.zetcode class BankAccount { private var balance: Double = 0.0 fun deposit(amount: Double) { if (amount > 0) { balance += amount } } fun getBalance(): Double = balance } fun main() { val account = BankAccount() account.deposit(100.0) println(account.getBalance()) // Output: 100.0 // account.balance = 500.0 // Error: Cannot access 'balance' }
在这里,balance
是私有的,只能通过 deposit
方法修改。禁止从类外部直接访问,确保对余额进行受控修改。
私有函数
私有函数是仅在其声明的类中可访问的辅助方法。它们有助于将复杂的操作分解为更小的步骤。
package com.zetcode class Calculator { fun add(a: Int, b: Int): Int { validateInput(a, b) return a + b } private fun validateInput(a: Int, b: Int) { require(a >= 0 && b >= 0) { "Inputs must be non-negative" } } } fun main() { val calc = Calculator() println(calc.add(5, 3)) // Output: 8 // calc.validateInput(2, 2) // Error: Cannot access 'validateInput' }
validateInput
函数是私有的,由 add
方法内部使用。外部代码无法直接调用此验证函数,从而保持验证逻辑的封装性。
私有构造函数
私有构造函数可防止直接实例化类。这对于单例模式或工厂方法很有用。
package com.zetcode class Database private constructor() { companion object { private var instance: Database? = null fun getInstance(): Database { if (instance == null) { instance = Database() } return instance!! } } fun query(sql: String) = println("Executing: $sql") } fun main() { val db = Database.getInstance() db.query("SELECT * FROM users") // val db2 = Database() // Error: Cannot access '' }
私有构造函数强制客户端使用 getInstance
获取一个 Database 对象。这确保只存在一个实例(单例模式)。实例变量也是私有的,以防止外部修改。
顶级声明中的私有
当用于顶级声明(在任何类之外)时,private 将可见性限制为当前文件。这对于文件特定的实用程序很有用。
package com.zetcode private const val MAX_RETRIES = 3 private fun logError(message: String) { println("ERROR: $message") } class NetworkClient { fun fetchData() { var attempts = 0 while (attempts < MAX_RETRIES) { try { // Network operation return } catch (e: Exception) { logError(e.message ?: "Unknown error") attempts++ } } } } // In another file: // fun test() { // println(MAX_RETRIES) // Error: Cannot access 'MAX_RETRIES' // logError("Test") // Error: Cannot access 'logError' // }
常量 MAX_RETRIES
和函数 logError
都对该文件是私有的。它们可以在文件中使用,但无法从其他文件访问,即使在同一包中也是如此。
私有 Setter
属性可以具有私有 Setter,同时保持 Getter 为公共。这允许对外部代码进行只读访问,同时允许内部修改。
package com.zetcode class User(name: String) { var name: String = name private set fun changeName(newName: String) { if (newName.isNotBlank()) { name = newName } } } fun main() { val user = User("Alice") println(user.name) // Output: Alice user.changeName("Bob") println(user.name) // Output: Bob // user.name = "Charlie" // Error: Cannot assign to 'name' }
name
属性具有公共 Getter,但具有私有 Setter。外部代码可以读取名称,但只能通过 changeName
方法修改它,该方法可以强制执行验证规则。
嵌套类中的私有
嵌套类中的私有成员的行为类似于常规类,可见性仅限于嵌套类作用域。
package com.zetcode class Outer { private val outerSecret = "Outer secret" inner class Inner { private val innerSecret = "Inner secret" fun revealSecrets() { println(outerSecret) // Can access outer's private members println(innerSecret) } } fun testInner() { val inner = Inner() inner.revealSecrets() // println(inner.innerSecret) // Error: Cannot access 'innerSecret' } } fun main() { val outer = Outer() outer.testInner() // println(outer.outerSecret) // Error: Cannot access 'outerSecret' }
内部类可以访问其外部类的私有成员,但内部类的私有成员无法被外部类访问。两个类的私有成员都无法从 Outer 类外部访问。
接口中的私有
从 Kotlin 1.4 开始,Kotlin 接口可以具有私有函数。这些函数只能在接口及其实现中使用。
package com.zetcode interface Logger { fun log(message: String) private fun formatMessage(message: String): String { return "[${System.currentTimeMillis()}] $message" } fun logWithTimestamp(message: String) { log(formatMessage(message)) } } class ConsoleLogger : Logger { override fun log(message: String) { println(message) } } fun main() { val logger = ConsoleLogger() logger.logWithTimestamp("Hello, Kotlin!") // logger.formatMessage("Test") // Error: Cannot access 'formatMessage' }
formatMessage
函数对 Logger 接口是私有的。它可以被其他接口成员(如 logWithTimestamp
)使用,但无法被实现类或外部代码访问。
private 关键字的最佳实践
- 默认为 private: 默认情况下将成员设为私有,并且仅公开必要的内容。
- 封装状态: 使用具有受控访问方法 的私有属性来维护对象完整性。
- 隐藏实现: 保持辅助方法私有,以简化您的公共 API。
- 考虑可见性: 选择仍然允许必要访问的最严格的可见性。
- 记录公共 API: 重点关注公共成员的文档,因为私有成员是实现细节。
来源
本教程深入介绍了 Kotlin 的 private
关键字,展示了各种应用,包括属性、函数、构造函数和嵌套类。正确使用私有可见性可以促进封装,并通过隐藏实现细节来创建更易于维护的代码。
作者
列出 所有 Kotlin 教程。