cob*_*uck 8 java access-modifiers
这是场景.作为公开许可的开源API的创建者,我的团队创建了一个基于Java的Web用户界面框架(那么还有什么新东西?).为了在Java中保持良好和有条理,我们使用了命名约定org.mygroup.myframework.x的包,其中x是组件,验证器,转换器,实用程序等等(同样,还有什么是新?).
现在,org.mygroup.myframework.foo.Bar类中的某个地方是void doStuff()我需要执行特定于我的框架的逻辑的方法,我需要能够从我的框架中的其他几个地方调用它,例如org. mygroup.myframework.far.Boo.鉴于Boo既不是Bar的子类也不是完全相同的包,所以方法doStuff()必须声明为public才能被Boo调用.
但是,我的框架作为一种工具存在,允许其他开发人员为其客户创建更简单,更优雅的RIA.但是,如果com.yourcompany.yourapplication.YourComponent调用doStuff(),则可能会产生意外和不良后果.我希望永远不会允许这种情况发生. 请注意,Bar包含其他真正公开的方法.
在象牙塔世界中,我们将重写Java语言并将标记化模拟插入到默认访问中,这将允许我们选择的包结构中的任何类访问我的方法,可能类似于:
[org.mygroup.myframework.*] void doStuff() { .... }
Run Code Online (Sandbox Code Playgroud)
其中通配符是指任何以org.mygroup.myframework开头的包可以调用的类,但没有其他人.
鉴于这个世界不存在,我们还有什么其他好的选择?
请注意,这是由现实生活场景推动的; 名称已被更改以保护有罪.存在一个真正的框架,在其整个Javadoc中,人们会发现公共方法被评论为"这种方法是内部的MYFRAMEWORK而不是其公共API的一部分.请不要打电话!!!!!!" 一些研究表明这些方法是从框架内的其他地方调用的.
事实上,我是一名使用相关框架的开发人员.虽然我们的应用程序已经部署并且取得了成功,但我的团队遇到了很多挑战,我们希望说服我们的老板再也不要使用这个框架了.我们希望通过对框架开发人员做出的糟糕设计决策的深思熟虑的演示来做到这一点,而不仅仅是作为一个咆哮.这个问题将是我们观点中的一个(但有几个),但我们无法理解我们如何以不同的方式完成它.在我的工作场所已经有了一些热烈的讨论,所以我想知道世界其他地方会怎么想.
更新:到目前为止,对两个回答者没有冒犯,但我认为你错过了这个标记,或者我没有表达好.无论哪种方式,我都可以尝试照亮事物.尽可能简单地说,框架的开发人员应该如何重构以下内容.请注意,这是一个非常粗略的例子.
package org.mygroup.myframework.foo;
public class Bar {
/** Adds a Bar component to application UI */
public boolean addComponentHTML() {
// Code that adds the HTML for a Bar component to a UI screen
// returns true if successful
// I need users of my framework to be able to call this method, so
// they can actually add a Bar component to their application's UI
}
/** Not really public, do not call */
public void doStuff() {
// Code that performs internal logic to my framework
// If other users call it, Really Bad Things could happen!
// But I need it to be public so org.mygroup.myframework.far.Boo can call
}
}
Run Code Online (Sandbox Code Playgroud)
另一个更新:所以我刚刚了解到C#具有"内部"访问修饰符.因此,提出这个问题的更好方法可能是"如何在Java中模拟/模拟内部访问?" 不过,我并不是在寻找新的答案.我们的老板最终同意上述问题
当您提到文档问题时,您就最接近答案了。真正的问题不是你无法“保护”你的内部方法;而是你无法“保护”你的内部方法。相反,内部方法会污染您的文档并引入客户端模块可能错误调用内部方法的风险。
当然,即使您确实拥有细粒度的权限,您仍然无法阻止客户端模块调用内部方法——jvm 无论如何都无法防止基于反射的对私有方法的调用。
我使用的方法是为每个有问题的类定义一个接口,并让该类实现它。接口可以仅根据客户端模块来记录,而实现类可以提供您想要的内部文档。如果您不愿意,您甚至不必在分发包中包含实现 javadoc,但无论哪种方式,边界都是明确划分的。
只要您确保在运行时每个文档接口仅加载一个实现,现代 jvm 将保证您不会因使用它而遭受任何性能损失;并且,您可以在测试期间加载线束/存根版本以获得额外的好处。