我70%确信这是不可能的,但有没有办法确保子类具有特定的构造函数或工厂方法?
在这种情况下,我试图创建一个StringSerializable
,要求子类具有以下方法
toString
,将对象转换为String
。fromString
,它从String
获取实例。显然,在第一种情况下,我可以将toString
抽象化。另一方面,拥有非静态fromString
似乎有问题。但是,我无法创建抽象的静态方法。我也不认为构造函数是完全合适的。
答案 0 :(得分:3)
你是对的;在编译时强制它是不可能的。您可以在运行时执行各种技巧(例如在测试中使用反射),但这就是它。
但问问自己:为什么你想要那个?你不能动态地调用静态方法或构造函数(通过反射除外),那么如果你拥有它们,你将如何使用这些必需的工厂呢?
如果只是为了代码的一致性(这是一件好事!),那么在开发代码库时,您只需要确保一致性。基类中的注释可以在这里发挥很大作用,代码评论和其他“软”技术也可以。
如果计划在反射中使用工厂,那么可以在测试中使用类似的反射来确保每个子类都有它所需的位。
另一个选择是创建一个非静态工厂:
public interface FooMaker() {
Foo create(String arg);
}
...并使用它,而不是静态fromString
方法。
你又遇到了同样的问题:“如何确保每个子类都有FooMaker
实现?”我会说你不应该担心这一点。如果将FooMaker
作为代码的“起点”,而不是子类,那么子类正在做什么并不重要;重要的是,您的FooMaker
会为您提供一种从字符串转到Foo
的方式,并且每个Foo
都可以返回字符串。
答案 1 :(得分:0)
以下代码确保每个子类都需要实现静态方法,如果子类没有实现该方法,它将在构造类时失败,尽可能接近编译时错误,但不能编译时间
抛出的异常非常清楚,程序启动时会立即失败
public abstract class Base {
static Functional test;
static {
if(test == null) {
throw new RuntimeException("You need to provide an implementation for the implemntMe method in class base");
}
}
private interface Functional {
Base implementMe(int whatever, boolean anotherParameter);
}
public static void main(final String[] args) {
}
}
私有接口构造确保只能使用lambdas来实现方法
子类必须看起来像这样
public SubClass extends Base {
static {
test = (int whatever, boolean anotherParameter) -> {
Subclass tmp = new Subclass();
//construct object
tmp.setWhatever(whatever);
return tmp;
}
}
}
lamdas就像实现功能接口的内联方法,只有一个抽象方法的接口
您还可以在任何其他地方公开声明该接口,并使用匿名内部类实现它, 但是我的方法确保程序员必须复制并粘贴代码才能重用它, 或者需要从另一个类
复制Functional的对象