我是否可以提供一个接口,让其他类允许我访问它的私有变量



首先澄清一下:我所说的"接口"是指组件之间的任何交互点,不一定是"抽象类型"那种接口。(虽然如果我可以使用这样的接口来做到这一点,那就太好了。)

我正在编写一个被设计为可扩展的类。问题域是全局优化,因此任何继承我的类的最终用户程序员(我将称他们为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注释的字段。然后,它将用户输入写入这些字段。它不需要看起来完全像这样,有注释和所有的,但是你知道的。

当然,这个问题是foobar是私有的,MyFrameworkClass中的代码不能写入它们,即使是反射。如果它们是包私有的,也没有帮助,因为Steve的代码不会和我的在同一个包中,我宁愿不要求他将它们公开,或者添加任何其他接口,允许除了我以外的任何人访问这些字段。

有什么方法可以做我想要的,无论是通过摆弄SecurityManager还是做一些完全不同的事情?

如果我在您的位置,我会试图找到一种方法来使用Spring框架来为我做这件事。这样用户就可以这样写:

@Component
public class SteveClass {
    @Value("${steve.foo}")
    private int foo;
    @Value("${steve.bar}")
    private String bar;
    private boolean baz;
    @Autowired(required = false)
    private DaveClass dave;
}

你所要做的就是建立一个上下文,其中有这些属性可用;这是微不足道的。(Spring确实会在安全场景背后摸索,但它是以"正确"的方式这样做的;您所需要做的就是确保Spring是受信任的,并且您的其余代码几乎不需要相同级别的权限。)当然,它也给了史蒂夫很多其他的工具来帮助他建立自己的应用程序,但这是另一个问题的故事。

您可以使用Class.getDeclaredFields来获取所有类的声明字段(包括非公共字段),然后使用Field.setAccessible(true)来访问它。

Field foo = HasPrivate.class.getDeclaredField("foo");
foo.setAccessible(true);
SteveClass steve = new SteveClass();
System.out.println(steve); // "0" -- I set up SteveClass.toString() to just print foo
foo.setInt(hp, 1234);
System.out.println(steve); // "1234"

但这意味着你依赖于SecurityManager来允许你这样做。默认情况下是这样的,但这可能不适用于所有用户。如果这是一个令人望而却步的要求,还有其他不太方便但可能更健壮的选项(比如要求构造函数接受一个Configuration对象,然后用户可以从中获取值)。

  1. 创建Configuration接口

    interface Configuration
    {
        int foo ( ) ;
        String bar ( ) ;
    }
    
  2. 使用Configuration界面

    public class SteveClass extends MyFrameworkClass {
        private Configuration configuration ;
        // implementations of my abstract methods, etc.
    }
    

我想这就是所谓的委托

相关内容

  • 没有找到相关文章

最新更新