我绞尽脑汁试图找到一种简单的方法来强制子类声明另一种类型的子类。例如,我有
public final class MessageType1 extends MessageType {
public static final class Subtypes extends MessageSubtypes {
public static int SOME_SUBTYPE = 1;
}
}
public final class MessageType2 extends MessageType {
public static final class Subtypes extends MessageSubtypes {
public static int ANOTHER_SUBTYPE = 1;
}
}
public abstract class MessageType {
public static abstract class MessageSubtypes {
public static int ALL_SUBTYPES = 0;
}
}
有没有办法确保MessageType的每个子节点都必须创建自己的MessageSubtypes版本并将其命名为Subtypes?
或者也许我在错误的圈子中旋转,并且有更好的方法来做到这一点。基本上我只是想确保我的所有消息类型都有自己的一组唯一子类型,并且每个子类型都有一个名为ALL的成员,其值为0.创建没有子类型的MessageType不应该编译,但如果不可能它应该至少不可用,如果发生则抛出异常。
答案 0 :(得分:6)
如何强制子类声明特定的内部类?
你不能。
您可以做的最多是声明子类型必须实现的abstract
方法。在您的情况下,您可以声明方法abstract Set<MessageSubtype> getSubtypes()
。
请注意,我将名称更改为单数。此外,对于子类型,使用enum
而不是class
几乎肯定会更好,因为枚举是最佳方式来表示 fixed < / strong>在编译时已知的类型值集。
基本上我只是想确保我的所有消息类型都有自己的一组唯一子类型,并且每个子类型都有一个名为ALL的成员,其值为0.创建没有子类型的MessageType不应该编译,但如果这是不可能的,它至少应该不可用,如果发生则抛出异常。
您对实现过多考虑,而对代码公开的API却不够。我认为几乎每个中级Java程序员都试图在某些时候做这样的事情(我当然有!)。考虑为代码的使用者提供使用的界面。
答案 1 :(得分:1)
我不认为超级类能够知道它们是否或如何被子类化。
您可以创建枚举并让get方法返回该类型的值。这可能会使子类明确表示他们应该更改枚举以添加自己的类型。
更大的问题是:为什么你认为这是必要的?类名应该是关于类型的足够信息吗?你的设计不会破坏多态性和动态绑定的目的吗?
答案 2 :(得分:1)
检查基类的构造函数:
class BaseClass {
public BaseClass() {
assert isValidSubclass() : getClass() + " does not contain a suitable inner class";
...
}
private boolean isValidSubclass() {
Class<?> cl = getClass();
// Maybe cache the test results in a static thread-safe table.
for (Class<?> innerClass : cl.getDeclaredClasses()) {
if (/* is suitable according to your criteria*/) { return true; }
}
return false;
}
}
只要您在启用断言的情况下运行测试,这将导致它们在第一次尝试构造未声明合适内部类的子类实例时出现故障。
答案 3 :(得分:0)
我开始认为我是在过分思考,应该保持简单。虽然我的目标是强制每个人都拥有一个ALL,但有可能有一天可能是一个不允许订阅其所有消息的子类型。我想用以下方法简化:
public abstract class MessageType {
protected static class BaseMessageSubtype {
public static int ALL = 0;
}
}
public class OrderMessageType extends MessageType {
public static class MessageSubtype extends BaseMessageSubtype {
public static int SETTLED = ALL + 1;
public static int OPENED = ALL + 2;
public static int CLOSED = ALL + 3;
public static int VOIDED = ALL + 4;
public static int CHANGED = ALL + 5;
}
}
仍然会使用.Subtype进行调用。但如果有人真的想要他们可以拒绝一切。我不能强制要求每种类型都有一个Subtype类,但这可能不是问题。只要有人最终可以引用其子类型具有整数值的消息类型,我们就可以了。有可能有人可能会覆盖全部为0的0并且意外地收到太多消息,但该项目现在完全是内部的,因此不太可能很快发生。
答案 4 :(得分:-1)
嵌套类不参与多态(就像字段一样),因此这通常是不恰当的方法。像Python这样更具动态性的语言可能更适合您想要实现的目标。
但是,您能描述这些子类型的功能吗?或许可以更好地定义这样的接口/抽象类:
class MessageType {
public abstract MessageSubtype[] getSubtypes(); // to enumerate them
public instantiateSubType(<some kind of type discriminator>); // basically a factory function.
}
您可能需要查看Abstract factory pattern