为什么公共课不能扩展私人课程?

net*_*men 9 kotlin

我有以下类层次结构:

interface Repository

// This class contains some common stuff for LocalRepository and RemoteRepository. I'm never going to use this class outside this file, so I make it private
private abstract  class BasicRepositoryImpl

// these classes are designed to be instantiated in other files    
class LocalRepository : BasicRepositoryImpl(), Repository // error

class RemoteRepository : BasicRepositoryImpl(), Repository // error
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误:

子类有效可见性'public'应该与其超类有效可见性'private'相同或更不宽容

我不想BasicRepositoryImpl在其他任何地方使用,所以它已声明private,我想在其他文件中使用LocalRepository,RemoteRepository如下所示:

class Presenter(val repo: Repository)

val p = Presenter(LocalRepository())
Run Code Online (Sandbox Code Playgroud)

但是这个错误阻止我创建这样的层次结构.为什么?它出什么问题了?

Jay*_*ard 11

类和它的祖先必须全部是从使用类访问.否则在加载祖先类时会违反,而不仅仅是调用其方法或使用其功能.在存在可访问性的所有情况下,Kotlin都非常清楚和清楚.

它开了一个小会允许的事情,以后可能会导致真正的JVM访问冲突,就像一个inline公共类函数,内联到另一个类,调用民办非访问一些始祖.如果您觉得可以像这样做一个混合模型的可访问性,那么你有很多漏洞没有考虑.考虑因素的范围大于仅隐藏实例化的某些类的愿望.

由于类是抽象的,除了作为祖先之外,它不能直接使用,所以你已经有了一些保护.如果你想阻止在你的模块之外使用它作为一个祖先,那么创建它的构造函数private或者internal那将解决这个问题:

abstract class BasicRepositoryImpl private constructor() { ... }
Run Code Online (Sandbox Code Playgroud)

现在你已经保护了直接实例化(abstract)或者使用它作为基类(通过使用abstract和私有构造函数),所以最后要做的就是给它一个好名字AbstractBaseRepository,按照惯例人们将不管它.

如果您想讨论"为什么"这是设计决策,技术限制或保护规则......那么请尝试在YouTrack中的论坛,功能或语言更改建议.但要注意事情并不像他们最初看起来那么简单.这些规则是有原因的(即使其他语言危险地允许).