在kotlin包装保护替代品

时间:2016-03-10 10:39:42

标签: visibility kotlin

在java中,我们为类提供了包受保护(默认)修饰符,它允许在单个包中包含许多类,但只暴露少量类并保持逻辑封装。

对于kotlin,似乎并非如此,如果我想让其他几个类彼此可见而不进一步,我必须使用私有修饰符来限制单个文件的可见性......所以基本上如果你在一个软件包中有10个类,其中只有一个是公开的,现在你将拥有一个包含所有类的大文件(并且private到处都有)...

这是正常做法还是有办法在kotlin中实现一些类似的模块化?

我不明白他们是否有包的概念为什么他们摆脱了包受保护的访问...

更新:我们可能会在所有之后获得包保护可见性 see the discussion here

4 个答案:

答案 0 :(得分:31)

与Java相比,Kotlin似乎在较小程度上依赖于包模型(例如,目录结构未绑定到包)。相反,Kotlin提供internal visibility,它是为模块化项目架构而设计的。使用它,您可以将部分代码封装在单独的module

因此,在顶级声明中,您可以使用

  • private限制对文件的可见性
  • internal限制对模块的可见性

此时,没有其他可见性限制选项。

答案 1 :(得分:5)

作为我在android上的解决方法,我创建了@PackagePrivate批注和lint检查来控制访问。 Here您可以找到项目。

棉绒检查显然不像编译器检查那样严格,并且需要一些设置才能使错误建立失败。但是android studio会自动进行皮棉检查,并在键入时立即显示错误。不幸的是,我不知道从自动填充中排除带注释的成员的方法。

而且,由于lint是纯粹的编译时工具,因此在运行时不会执行任何检查。

答案 2 :(得分:3)

正如@hotkeys指出的那样,您可以在module中使用internal关键字。我经常使用eclipse和maven,创建这些模块对我来说是不切实际的。

对于IDEA或Gradle的不同技术堆栈,它更实用;我不知道,因为我从未使用过它们。

另一个选择是将一个包的所有类放在一个文件中。这并不总是实用或优雅。

对我来说,package可见性对其记录价值非常有帮助。我想知道一些包提供给项目其余部分的公共接口。我想隐藏工厂实现类等等。

因此,即使可以在Java中破解自己的包私有类和方法,我仍然希望使用package关键字。

我所做的是创建一个带有单个注释的项目:

package com.mycompany.libraries.kotlinannotations;

import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.SOURCE;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Retention(SOURCE)
@Target({ TYPE, METHOD, CONSTRUCTOR })
/**
 * Use in Kotlin code for documentation purposes. 
 * 
 * Whenever a Kotlin class or method is intended to be accesible at package level only.
 *
 */
public @interface PackagePrivate {

}

然后我可以在任何Kotlin项目中使用此注释。

第二步,我还没有解决,我想在某个时候做,是创建一个PMD规则来强制执行maven(或任何其他构建工具),也是能够通过pmd插件查看我的IDE中违反规则的行为。

目前Kotlin还不是pmd支持的语言之一(即有自己的模块)。但PMD正处于积极发展阶段,Kotlin的受欢迎程度越来越高,因此有可能在某些时候开发出来。这只是我最好的猜测。

答案 3 :(得分:0)

基于包的保护在 Kotlin 中毫无意义,因为包本身不受保护

在 Java 中,包与目录结构相关。因此,如果您将类放在 com\example\yoursecretengine 中,那么任何在那里添加流氓类的尝试(有意或无意)都会很容易引起注意。这就是我们所依赖的安全性。

Kotlin 消除了目录和包之间的联系,因此我可以将我的类放在“我的”目录(例如src\java\pl\agent_l\illegalaccess)中,同时将其包声明为 com.example.yoursecretengine - 并获得对所有属性的访问权限你的意思是包私有。

事实上,Kotlin 项目无需任何包声明即可完美运行。这只是强调了包“更多的是您所说的指南而不是实际规则”。它们是一项便利功能,仅用于整理命名空间,仅此而已。

相关quotes from kotlinlang

<块引用>

与许多其他语言不同,Kotlin 包不要求文件具有任何特定位置 w.r.t.本身;文件与其包之间的连接仅通过包头建立。

还有:

<块引用>

文件中没有包头意味着它属于特殊的根包。