Java,如何停止从调用特定抽象 class 构造函数继承 classes,除了其中之一?

Java, how to stop inheriting classes from calling a particular abstract class constructor, apart from one of them?

我有一个抽象 class 和几个扩展它的具体 class。

抽象class有两个构造函数。我希望其中一个构造函数只能在一个特定的具体 class.

中调用

(我确实知道 Java 状态机的 enum 模式,但是两个级别的子 classing(和不可变的 POJO)更适合我遇到的问题求解。)

public abstract class SuperState {
    public final long mValue;
    protected SuperState(long value) { mValue = value; }
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
    ...
}

public class FirstState extends SuperState {
    public FirstState() { super(0); }
    ...
}

public class SecondState extends SuperState {
    public SecondState(SuperState last) { super(last); }
    ...
}

public class ThirdState extends SuperState {
    public ThirdState(SuperState last) { super(last); }
    ...
}

我想让任何子class(除了FirstState)调用SuperState(long value)构造函数时出现编译时(或至少运行时)错误。

我能否找出在 SuperState 构造函数中构造的具体 class 的类型,如果不符合预期则抛出运行时异常?

是否有针对抽象 class 的 "preferred" 具体 class,以便它具有某种形式的额外访问权限?

我能想到的一种方法,虽然我觉得它很丑:

protected SuperState(long value) 
{
    if (!this.getClass().getName().equals("SomeConcreteClassName"))
        throw new SomeException ();
    mValue = value; 
}

尽管 Tom 关于将 FirstState class 与 SuperState 放在同一个包中并使用包私有访问的评论听起来更好。

我认为实现它的唯一方法是使用 "friend" 的模拟。诀窍是在 FirstState 中拥有私有值 class,这只能由 FirstState 构造。其他 classes 可以看到 FirstState.Value class,但不能实例化它。

abstract class SuperState {
    public final long mValue;
    protected SuperState(FirstState.Value value) { mValue = value.value; }
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
}

class FirstState extends SuperState {
    public static class Value { private Value() {} }
    private static Value value = new Value();

    public FirstState() { super(value); }
}

class SecondState extends SuperState {
    public SecondState(SuperState last) { super(last); }
}

您可以像这样使用默认访问修饰符来做到这一点:

package a;

public abstract class SuperState {
    public final long mValue;
    SuperState(long value) { mValue = value; } // constructor has default access modifier
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
    ...
}



package a;

public class FirstState extends SuperState {
    public FirstState() { super(0); }
    ...
}



package b;
// is not able to access constructor SuperState(long) ie. calling contructor
// SuperState(long) will result in compile time error
public class SecondState extends SuperState {
    public SecondState(SuperState last) { super(last); }
    ...
}

我觉得你不清楚自己在做什么。 你是说 SuperState 有一个构造函数,它只能从一个特定的实现中调用。为什么?那个 subclass 很特别吗?为什么其他实现不应该调用它?

如果 FirstState 如此特别,也许您想将其作为内部 class:

public abstract class SuperState {
  public final long mValue;
  private SuperState(long value) { mValue = value; }
  protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
  ...
  public static class FirstState {
    //Can call SuperState(long) from here
  }
}

如果这对您来说似乎不合适,那么您可能应该将两个构造函数都打开。 如果在我看来,你正在制作一个链状结构,那么你可能甚至不想将 FirstState 作为可访问的 class:

public abstract class SuperState {
  public final long mValue;
  private SuperState(long value) { mValue = value; }
  protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
  ...
  private static class FirstState extends SuperState {
    private FirstState() { super(0); }
  }
  public static SuperState getFirstState() { return new FirstState(); }
}