强制子类具有特定的工厂方法或构造函数
Forcing subclasses to have a particular factory method or constructor
我有 70% 的把握认为这是不可能的,但是有没有办法确保子类具有特定的构造函数或工厂方法?
在这种情况下,我试图创建一个 StringSerializable
需要子类具有以下方法
toString
,将对象转换为 String
.
fromString
,从 String
. 获取实例
显然,在第一种情况下,我可以将 toString
抽象化。另一方面,具有非静态 fromString
似乎是有问题的。但是,我无法创建抽象静态方法。我也不认为构造函数是完全合适的。
你是对的;在编译时强制它是不可能的。您可以在运行时执行各种技巧(例如在测试中使用反射),仅此而已。
但问问自己:为什么你想要这样?您不能动态调用静态方法或构造函数(通过反射除外),那么如果您有这些所需的工厂,您将如何使用它们?
如果只是为了代码的一致性(这是一件好事!),那么您只需在开发代码库时确保一致性即可。基础 class 中的评论可以在这里发挥很大作用,代码审查和其他 "soft" 技术也可以。
如果您打算在反射中使用工厂,那么可以在测试中使用类似的反射来确保每个子class 都有它需要的位。
另一种选择是创建非静态工厂:
public interface FooMaker() {
Foo create(String arg);
}
...并使用它,而不是静态 fromString
方法。
您又遇到了与 "how do I ensure that every subclass has a FooMaker
implementation?" 相同的问题,我想再说一遍,您不必为此担心。如果您将 FooMaker
设为代码的 "starting point",而不是 subclass,那么 subclass 在做什么并不重要;重要的是您的 FooMaker
为您提供了从字符串到 Foo
的方法,并且每个 Foo
都有返回字符串的方法。
下面的代码确保每个subclass都需要实现静态方法,如果subclass没有实现该方法,那么在构造classes时会失败,尽可能接近编译时错误,但不是在编译时
抛出的异常很清楚,程序一启动就瞬间失败
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) {
}
}
私有接口构造确保只能使用 lambda 来实现该方法
子class 必须看起来像这样
public SubClass extends Base {
static {
test = (int whatever, boolean anotherParameter) -> {
Subclass tmp = new Subclass();
//construct object
tmp.setWhatever(whatever);
return tmp;
}
}
}
lamdas 就像实现功能接口的内联方法,一个只有一个抽象方法的接口
你也可以在任何其他地方公开声明接口并使用匿名内部实现它class,
但我的方式确保程序员必须复制和粘贴代码才能重用它,
或者需要从另一个 class
复制 Functional 的对象
我有 70% 的把握认为这是不可能的,但是有没有办法确保子类具有特定的构造函数或工厂方法?
在这种情况下,我试图创建一个 StringSerializable
需要子类具有以下方法
toString
,将对象转换为String
.fromString
,从String
. 获取实例
显然,在第一种情况下,我可以将 toString
抽象化。另一方面,具有非静态 fromString
似乎是有问题的。但是,我无法创建抽象静态方法。我也不认为构造函数是完全合适的。
你是对的;在编译时强制它是不可能的。您可以在运行时执行各种技巧(例如在测试中使用反射),仅此而已。
但问问自己:为什么你想要这样?您不能动态调用静态方法或构造函数(通过反射除外),那么如果您有这些所需的工厂,您将如何使用它们?
如果只是为了代码的一致性(这是一件好事!),那么您只需在开发代码库时确保一致性即可。基础 class 中的评论可以在这里发挥很大作用,代码审查和其他 "soft" 技术也可以。
如果您打算在反射中使用工厂,那么可以在测试中使用类似的反射来确保每个子class 都有它需要的位。
另一种选择是创建非静态工厂:
public interface FooMaker() {
Foo create(String arg);
}
...并使用它,而不是静态 fromString
方法。
您又遇到了与 "how do I ensure that every subclass has a FooMaker
implementation?" 相同的问题,我想再说一遍,您不必为此担心。如果您将 FooMaker
设为代码的 "starting point",而不是 subclass,那么 subclass 在做什么并不重要;重要的是您的 FooMaker
为您提供了从字符串到 Foo
的方法,并且每个 Foo
都有返回字符串的方法。
下面的代码确保每个subclass都需要实现静态方法,如果subclass没有实现该方法,那么在构造classes时会失败,尽可能接近编译时错误,但不是在编译时
抛出的异常很清楚,程序一启动就瞬间失败
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) {
}
}
私有接口构造确保只能使用 lambda 来实现该方法
子class 必须看起来像这样
public SubClass extends Base {
static {
test = (int whatever, boolean anotherParameter) -> {
Subclass tmp = new Subclass();
//construct object
tmp.setWhatever(whatever);
return tmp;
}
}
}
lamdas 就像实现功能接口的内联方法,一个只有一个抽象方法的接口
你也可以在任何其他地方公开声明接口并使用匿名内部实现它class, 但我的方式确保程序员必须复制和粘贴代码才能重用它, 或者需要从另一个 class
复制 Functional 的对象