繁体   English   中英

Java,除了其中一个之外,如何停止继承类调用特定的抽象类构造函数?

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

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

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

(我确实知道Java状态机的enum模式,但是两级子类化(和不可变的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); }
    ...
}

我想让它成为任何子类(除了FirstState之外)的编译时(或至少运行时)错误,以调用SuperState(long value)构造函数。

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

是否有一个抽象类的“首选”具体类,以便它具有某种形式的额外访问?

我想你不清楚你在做什么。 你说SuperState有一个只能从一个特定实现调用的构造函数。 为什么? 那个子类特别吗? 为什么其他实现不应该这样称呼?

如果FirstState如此特别,也许您希望将其作为内部类:

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作为可访问的类:

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(); }
}

我能想到的一种方式,虽然我发现它很难看:

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

虽然Tom关于将FirstState类放在与SuperState相同的包中并使用包私有访问的评论听起来更好。

我认为实现它的唯一方法是使用“朋友”的模拟。 诀窍是在FirstState拥有私有Value类,只能由FirstState 其他类可以看到FirstState.Value类,但无法实例化它。

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); }
    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM