Kotlin如何隐藏作为泛型参数的内部持久化对象?
解决Kotlin中隐藏持久化对象的问题
核心问题在于你当前的EmailImpl类是public的(Kotlin类默认public),即便构造器设为internal,它继承的BBase<PEmail>会把internal的PEmail暴露给外部,这违反了Kotlin的可见性规则——public类型不能依赖internal类型作为公开签名的一部分。而Java因为类型擦除,不会检查这一点。
下面是两种可行的解决方式:
方式一:完全隐藏内部实现类(推荐)
把所有和持久化相关的类都设为internal,对外只暴露业务接口和工厂方法,外部代码永远接触不到内部的PEmail、BBase和EmailImpl:
// 对外暴露的业务接口(public) interface BEmail { fun sendEmail() } // 内部持久化类,完全隐藏 internal class PEmail(val address: String, val content: String) // 内部基类,仅给实现类用 internal abstract class BBase<P>(internal val persistent: P) // 内部业务实现类,仅内部可见 internal class EmailImpl(persistent: PEmail) : BEmail, BBase<PEmail>(persistent) { override fun sendEmail() { // 这里可以直接使用persistent的属性做业务逻辑 println("Sending email to ${persistent.address}: ${persistent.content}") } } // 对外提供的工厂方法,返回业务接口实例 fun createEmail(address: String, content: String): BEmail { return EmailImpl(PEmail(address, content)) }
外部代码只能通过createEmail获取BEmail实例,完全看不到内部的持久化细节,彻底实现了PEmail的隐藏。
方式二:用标记接口隔离泛型依赖
如果你的BBase需要对外暴露部分能力,但不想暴露具体的PEmail,可以定义一个public的标记接口,让PEmail实现它,再用这个接口作为BBase的泛型参数:
// 对外的标记接口,仅用于泛型约束 interface PersistentObject // 内部持久化类,实现标记接口 internal class PEmail(val address: String) : PersistentObject // 基类用标记接口作为泛型参数,对外仅暴露标记接口类型 abstract class BBase<P : PersistentObject>(internal val persistent: P) // 内部业务实现类 internal class EmailImpl(persistent: PEmail) : BEmail, BBase<PEmail>(persistent) // 工厂方法返回BEmail fun createEmail(address: String): BEmail { return EmailImpl(PEmail(address)) }
这种方式适合需要BBase对外提供通用能力,但又不想暴露具体持久化类的场景。
内容的提问来源于stack exchange,提问作者Wiła
相关产品推荐
相关产品推荐

