Java 如何强制子类声明特定的内部类

Java 如何强制子类声明特定的内部类,java,Java,我绞尽脑汁试图找到一种简单的方法来强迫一个子类声明另一种类型的子类。例如,我有 public final class MessageType1 extends MessageType { public static final class Subtypes extends MessageSubtypes { public static int SOME_SUBTYPE = 1; } } public final class MessageType2 exte

我绞尽脑汁试图找到一种简单的方法来强迫一个子类声明另一种类型的子类。例如,我有

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的每个子级都必须创建自己版本的MessageSubtype并将其命名为Subtype

或者我转错了圈,有更好的方法。基本上,我只是想确保我的所有消息类型都有自己独特的子类型集,并且每个子类型都有一个名为all的成员,其值为0。不应编译创建没有子类型的MessageType,但如果不可能,它至少应该不可用,并在发生异常时引发异常

如何强制子类声明特定的内部类

你不能。

您最多只能声明子类型必须实现的
abstract
方法。在本例中,您可以声明一个方法
抽象集getsubtype()


请注意,我将名称改为单数。此外,对于子类型,使用
enum
几乎肯定比使用
class
更好,因为enum是迄今为止表示编译时已知的固定类型值集的最佳方式


基本上,我只是想确保我的所有消息类型都有自己独特的子类型集,并且每个子类型都有一个名为all的成员,其值为0。不应编译创建没有子类型的MessageType,但如果不可能,它至少应该不可用,并在发生异常时引发异常


您对实现考虑太多,而对代码公开的API考虑得不够。我认为几乎每个中级Java程序员都会在某个时候尝试做类似的事情(我当然有!)。考虑为代码的使用者提供一个接口。

我不认为超类能够知道它们是否或者如何被子类化

您可以创建一个枚举,并让get方法返回该类型的值。这可能会让子类明白,它们应该修改枚举以添加自己的类型


更大的问题是:你为什么认为这是必要的?类名应该是关于类型的足够信息吗?您的设计是否违背了多态性和动态绑定的目的?

检查基类的构造函数:

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;
  }
}
类基类{
公共基类(){
断言isValidSubclass():getClass()+“不包含合适的内部类”;
...
}
私有布尔值isValidSubclass(){
Class cl=getClass();
//可能将测试结果缓存在静态线程安全表中。
对于(类innerClass:cl.getDeclaredClasses()){
如果(/*符合您的条件*/){return true;}
}
返回false;
}
}

只要在启用断言的情况下运行测试,当有人第一次尝试构造未声明合适内部类的子类实例时,就会导致测试快速失败。

嵌套类不参与多态性(就像字段不参与多态性一样),因此这通常是不合适的方法。像Python这样更具动态性的语言可能更适合您想要实现的目标

但是,您能否描述这些子类型的功能?这样定义一个接口/抽象类是否更好:

class MessageType {
    public abstract MessageSubtype[] getSubtypes(); // to enumerate them
    public instantiateSubType(<some kind of type discriminator>); // basically a factory function.
}
class消息类型{
public abstract MessageSubtype[]getsubtype();//枚举它们
public instanceSubtype();//基本上是一个工厂函数。
}

你可能想看看

我开始觉得我想得太多了,应该保持简单。虽然我的目标是强制每个人都有一个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进行调用。但是,如果有人真的想不允许一项法律,他们会竭尽全力。我不能强制要求每个类型都有子类型类,但这可能不是问题。只要有人最终能够引用子类型具有整数值的消息类型,我们就可以了。有人可能会覆盖0(即全部内容),并意外收到太多消息,但该项目目前完全是内部的,因此短期内不太可能发生。

我认为这两种情况都不可能发生。你能告诉我们你到底想做什么吗?我正在编写一个供多个类使用的通信桥,基本上是一个非常小的pub/sub引擎。我想让人们通过主题和副标题的组合来订阅。所有主题都必须定义一组子主题,并且所有子主题集都应该包含一个名为All的成员。我是我自己的消费者,尽管还有其他消费者。我不能只拥有一个接口。最终结果(具有自己子类型的顶级消息类型)是必需的。如果有更好的办法,我洗耳恭听。:)多态性和虚拟方法将是我的首选,但也许我并不真正理解您的需求。您能举例说明您的意思吗?如果它不允许像.Subtype.或更具体地说OrderMessage.Subtype.ORDER_这样的语句打开,那么对于我所处的情况,它将不会非常有用。再说一次,我可能想得太多了。我主要关心的是所有的子类型都必须有一个all,但我可能在试图通过类结构来强制实现这一点上做得太过火了。如果有人试图从他们的子类型中得到一个完整的结果,那么最好只是把评论放在这个效果上,让测试失败;这感觉就像订单的状态机。订单不会更改其类型,但其状态可以更改。我会把它模拟成一个州马赫