Java中更改接口常量的实用替代方法

Java中更改接口常量的实用替代方法,java,interface,implementation,extend,static-members,Java,Interface,Implementation,Extend,Static Members,假设您有一个包含多个类的Java项目,其中大多数类处理一些常量(数据集的属性,这些属性应该在实验开始时加载(基于数据集)) 为了能够在整个类中访问这些常量,一个非常合理的选择是将常量作为容器(对象/类/接口)的字段。为了让其他类利用容器字段,有5种方法 仅当字段是动态的时: 将容器传递给处理方法(处理所需常量的方法) 将容器放在方法类(方法所在的类)的字段中 然而,字段是动态的还是静态的(当容器是类时) 通过方法类扩展该字段的容器 仅当字段是静态的时 通过方法类实现该字段的容器 调用静

假设您有一个包含多个类的Java项目,其中大多数类处理一些常量(数据集的属性,这些属性应该在实验开始时加载(基于数据集))

为了能够在整个类中访问这些常量,一个非常合理的选择是将常量作为容器(对象/类/接口)的字段。为了让其他类利用容器字段,有5种方法

仅当字段是动态的时:

  • 将容器传递给处理方法(处理所需常量的方法)
  • 将容器放在方法类(方法所在的类)的字段中
然而,字段是动态的还是静态的(当容器是类时)

  • 通过方法类扩展该字段的容器
仅当字段是静态的时

  • 通过方法类实现该字段的容器
  • 调用静态字段(Container.field)
前两个选项和最后一个选项迫使您在代码中写入数十次或数百次容器名称+”。(例如,container.trainingListSize、container.numberOfUsers、Container.trainingListSize、Container.numberOfUsers,我正试图摆脱它;第三种选择迫使你成为一个特殊阶级的儿子,这个阶级有时与你的程序结构相矛盾。 它仍然只是最后的选择;但不幸的是,在Java接口中,接口的常量值是最终值,在程序开始加载属性文件时无法设置


看这个问题(),似乎提问者的情况和我一样;但是我还没有找到解决方案。

我认为您需要在软件架构中有明确的意图和分离关注点。你说的是“常量”,但你提到从文件中加载它们,所以这些毕竟不是真正的常量。这些更像是配置参数。如果这是正确的,您有几个选择

您可以将您的配置视为全局变量:在这种情况下,我建议创建一个单独的类,该类从文件中加载变量,并提供实用工具来访问这些变量,例如,<代码> MyCONFIG.Soad参数()/<代码>。请注意,您可以静态导入

MyConfig.
,因此只需使用
someParameter()
即可访问变量

您可以将您的配置视为其他容器或上下文的一部分,在这种情况下,您想要的语法很难,但是您必须需要注入<代码>上下文< /代码>,然后从代码中调用<代码>上下文。我不建议将此上下文类作为其他对象的基类,因为它肯定违反了关注点分离和OOP规则,即如果

Foo
不是
context
,则不应从它扩展。请注意,这基本上是您描述的第一个选项

我应该补充一点,只有在接口是静态和最终的情况下,才能在接口中定义成员。这并不奇怪,因为java不支持多重继承或“混合”。这是Java语言规范团队非常慎重的选择,我相信这是一个很好的选择。除非您使用java 8和定义的默认方法,这些方法依赖于从文件或某物读取的映射,例如

interface Config {
  Map<String, String> getProperties();
  default String someProperty() {
    return getProperties().get("some-prop");
  }
  // ... more utility methods follow
}
接口配置{
映射getProperties();
默认字符串someProperty(){
返回getProperties().get(“某些道具”);
}
//…更多实用方法随之而来
}
上面的接口定义了一组(仅显示一个)实用方法,这些方法返回由字符串设置键的字符串属性(可以是任何值)。在启动时,您可以将映射(例如由文件读取)注入到类中,并神奇地为您定义所有这些实用程序方法

使用此方法的类的代码如下所示:

class MyExperiment implements Config {
  private final Map<String, String> props;
  MyExperiment(Map<String, String> props) { this.props = props; }

  void someMethod() {
    // read property from injected configuration
    String someProp = someProperty();
  }
}
类MyExperiment实现配置{
私人最终地图道具;
MyExperiment(Map props){this.props=props;}
void方法(){
//从注入的配置读取属性
字符串someProp=someProperty();
}
}

这可能会为您节省一些输入,但仍然需要您的类实现
Config
并定义
getProperties()
方法,这违反了关注点分离,应该避免。

Java的一大好处是,它不提供全局变量或常量。这背后的原因是,全局性的东西使每个其他模块/类都可能依赖于这些东西。这再次使您的设计具有强耦合性,并且难以维护

因此,您需要做的是首先对变量/常量进行分组,以使其有意义。“容器”显然不是这样一个团体的好名字。尽量不要使用变量容器,而是尝试查找一个已经存在的类,该类已经包含支持与变量/常量相同概念的方法。请参阅java.lang.Math,以了解有关此方面的一个很好的示例。 在您的情况下,这可能是用于加载数据集的存储库类

接下来,您应该调查为什么要尝试从该类外部访问这些变量/常量。从其他类访问(大量)变量/常量通常表明设计不好。尝试根据职责对类进行分组,您可能会找到一种解决方案,其中只有那些变量/常量只能从它们所在的类中访问

所以基本上,如果你觉得你需要摆脱几百个