我有以下情况:
父类具有依赖于常量的函数。但是定义该常量的唯一有效位置是在子类中(父类不能定义常量值,但它可以与99%的用例中的常量未定义一起使用 - 该常量是默认使用,如果a缺少特定的配置元素。)
但是,我想强制执行从父类继承的任何子类必须定义常量的值,因为任何子类都必须能够使用另一个子类功能百分比。
在Java中实现此实施的最佳实践是什么,理想情况是在编译时?(显然,在运行时,我可以简单地检查使用它的方法中常量是否为空/空)
我自己的解决方案是将常量的值获取器实现为父类中的抽象方法,并将其与构造函数中的实际setter一起调用;像这样的东西:
public class HelperClass1 {
private String myConstant;
public void setMyConstant() {} // implemented obviousy
public void myMethod() { // Called from ParentClass's methods
// Do something useful with myConstant
}
}
import HelperClass1;
public abstract class ParentClass {
ParentClass() {
HelperClass1.setMyConstant( getMyConstantValue() );
}
public abstract void getMyConstantValue();
}
public class ChildClass1 extends ParentClass {
public void getMyConstantValue() { return "BUZZ"; }
}
public class ChildClass2 extends ParentClass {
} // Fails to compile without getMyConstantValue()
然而,(a)这个实现有一个问题(我不能使用ParentClass本身,因为它现在是抽象的)没有子类化; (b)由于我不是Java开发人员,我担心这不是最佳或最优雅的解决方案。所以我想知道是否有一种最佳实践方法可以改善我实施的内容。
答案 0 :(得分:4)
为父类提供两个构造函数:
一个是受保护的构造函数,它将常量作为参数。
另一个是私有构造函数,可以在不设置常量的情况下构造父类的实例。
为父类提供一个工厂方法,可以调用私有的非常量构造函数。
想要获取父类实例的类可以调用工厂方法。但是,想要从父类继承的子类必须调用受保护的构造函数,该构造函数可以验证是否传递了有效的常量。
public class ParentClass {
private final SomeClass myConstant;
protected ParentClass(SomeClass aConstant) {
if (null == aConstant) {
throw new IllegalArgumentException("...");
}
myConstant = aConstant;
}
private ParentClass() {
myConstant = null;
}
public static ParentClass getInstance() {
return new ParentClass();
}
}
public class ChildClass {
public ChildClass() {
super(new SomeClass(42));
}
}
这并不完美。有人可以编写一个将坏常量传递给超类构造函数的子类,并且在某些代码尝试构造子类的实例之前它实际上不会失败。
答案 1 :(得分:-1)
您可以使用Enum和Interface:
来完成 public interface CommonInterface {
public String getValue();
}
public enum EnumImp implements CommonInterface {
FIRST_EL("buzz"),
SECOND_EL("hello"),
THIRD_EL("hi");
private final String element;
private EnumImp(String element) {
this.element = element;
}
public String getElement() {
return this.element;
}
}
public abstract class ParentClass {
private CommonInterface _commonIntf;
/**
*
*/
public ParentClass(CommonInterface commonIntf) {
_commonIntf = commonIntf;
}
//Example method that will be inherit
public void invokeCommonInterface() {
_commonIntf.getValue();
}
}