我可以提供一个接口来允许另一个类让我访问它的私有变量吗?
首先,澄清一下:我所说的“接口”是指组件之间的任何交互点,不一定是“抽象类型”类型的接口。 (尽管如果我可以使用这样的接口来做到这一点,那就太好了。)
我正在编写一个旨在扩展的类。问题域是全局优化,因此任何对我的类进行子类化的最终用户程序员(我称他们为史蒂夫)将提供他们自己的问题和算法来解决它;我只是提供框架(网络、用户界面等)。 Steve 的程序可能需要任意数量的配置设置;我希望我的代码能够以与获取自己的设置相同的方式从用户那里获取这些设置(可以是从 GUI 控制面板、XML 配置文件或其他任何设置)。 Steve 不应该复制我的任何代码,也不应该破坏 Java 的类型安全或封装模型。
理想情况下,Steve 能够按照以下方式编写一些内容:
public class SteveClass extends MyFrameworkClass {
@Configurable
private int foo;
@Configurable
private String bar;
private boolean baz;
// implementations of my abstract methods, etc.
}
Configurable
是我要提供的注释,它指示带注释的变量是我应该从用户那里获取的配置设置。正如您所看到的,我还希望 Steve 能够声明其他实例变量供他自己内部使用,但我从未接触过。
我打算通过在 MyFrameworkClass
中包含一个方法来实现这一点,该方法将迭代 getClass().getDeclaredFields()
并识别具有 Configurable
的字段> 注释。然后它将用户输入写入这些字段。它不必看起来完全像这样,有注释等等,但你明白了。
当然,这样做的问题是 foo
和 bar
是私有的,MyFrameworkClass
中的代码无法写入它们,即使是反射式也是如此。如果它们是包私有的,那将无济于事,因为史蒂夫的代码不会与我的代码位于同一个包中,而且我不想要求他将它们公开,或者添加任何其他接口,允许除了我访问这些字段。
有没有办法做我想做的事情,要么通过摆弄 SecurityManager
要么做一些完全不同的事情?
First, a clarification: By "interface", I mean any point of interaction between components, not necessarily the "abstract type" kind of interface. (Although if I can use such an interface to do this, great.)
I'm writing a class which is designed to be extended. The problem domain is global optimization, so any end-user-programmer who subclasses my class (I'll call them Steve) will be providing their own problem and algorithm to solve it; I just provide the framework (networking, user interface, etc.). Steve's program might require any number of configuration settings; I want my code to be able to get those settings from the user the same way it gets its own settings (be that from a GUI control panel, an XML configuration file, or whatever). Steve should not have to duplicate any of my code, nor should he have to break Java's type safety or encapsulation model.
Ideally, Steve would be able to write something along these lines:
public class SteveClass extends MyFrameworkClass {
@Configurable
private int foo;
@Configurable
private String bar;
private boolean baz;
// implementations of my abstract methods, etc.
}
Configurable
is an annotation that I would provide, that indicates that the annotated variable is a configuration setting that I should get from the user. As you can see, I also want Steve to be able to declare other instance variables for his own internal use, that I never touch.
I was going to implement this by including a method in MyFrameworkClass
that would iterate through getClass().getDeclaredFields()
and identify the fields that have Configurable
annotations. It would then writes the user input to those fields. It doesn't have to look exactly like this, with annotations and all, but you get the idea.
The problem with this, of course, is that foo
and bar
are private and code in MyFrameworkClass
can't write to them, even reflectively. It wouldn't help if they were package-private, since Steve's code won't be in the same package as mine, and I'd rather not require him to make them public, or to add any other interface that would allow anyone but me to access the fields.
Is there any way to do what I want, either by fiddling with SecurityManager
or doing something completely different?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果我处于您的位置,我会尝试找到一种使用 Spring 框架来为我完成此操作的方法。然后,用户可以这样写:
您所要做的就是构建一个上下文,其中包含这些可用的属性;这是非常微不足道的。 (Spring 确实在安全场景后面探索,但它以“正确”的方式这样做;您需要做的就是确保 Spring 是可信的,并且代码的其余部分不需要几乎相同级别的权限.) 当然,它还为 Steve 提供了大量其他工具来帮助他构建应用程序,但这是另一个问题的故事了。
If I was in your position, I'd be trying to find a way to use the Spring framework to do this for me. That would then let users write this:
All you'd have to do then is to build a context that has those properties available within it; that's pretty trivial. (Spring does poke around behind the security scenes, but it does so in the “correct” way; all you need to do is to ensure that Spring is trusted, and the rest of your code doesn't need nearly the same level of permissions.) Of course, it also gives Steve plenty of other tools to help him build his app, but that's a story for another question.
您可以使用
Class.getDeclaredFields
获取类的所有声明字段(包括非公共字段),然后使用Field.setAccessible(true)
获取对其的访问权限。但这意味着您依赖 SecurityManager 来允许您执行此操作。默认情况下是这样,但这可能不适用于所有用户。如果这是一个令人望而却步的要求,还有其他不太方便但可能更强大的选项(例如要求构造函数采用 Configuration 对象,然后用户可以从中获取值)。
You can use
Class.getDeclaredFields
to get all of the class's declared fields (including non-public ones), and thenField.setAccessible(true)
to gain access to it.But that means you're depending on the SecurityManager to allow you to do that. It does by default, but that may not work for all users. If that's a prohibitive requirement, there are other, less convenient but potentially more robust options (like requiring that the constructor take a Configuration object, which the user can then get values from).
创建配置界面
使用配置界面
我认为这就是所谓的委托。
Create a Configuration interface
Use the Configuration interface
I think this is called delegation.