Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java,如何停止继承类调用特定的抽象类构造函数,除了其中一个?_Java_Constructor_Abstract Class - Fatal编程技术网

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

Java,如何停止继承类调用特定的抽象类构造函数,除了其中一个?,java,constructor,abstract-class,Java,Constructor,Abstract Class,我有一个抽象类和几个扩展它的具体类 抽象类有两个构造函数。我希望其中一个构造函数只能在一个特定的具体类中调用 (我确实知道Java状态机的enum模式,但对于我正在解决的问题,两个级别的子类化(和不可变POJO)效果更好。) 我想让任何子类(除了FirstState)调用SuperState(long value)构造函数时都会出现编译时(或至少运行时)错误 我是否可以找出在SuperState构造函数中构造的具体类的类型,并在不符合预期的情况下抛出运行时异常 对于抽象类是否有一个“首选”的具体

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

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

(我确实知道Java状态机的
enum
模式,但对于我正在解决的问题,两个级别的子类化(和不可变POJO)效果更好。)

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

我是否可以找出在
SuperState
构造函数中构造的具体类的类型,并在不符合预期的情况下抛出运行时异常


对于抽象类是否有一个“首选”的具体类,这样它就有了某种形式的额外访问权?

我可以想到一种方法,尽管我觉得很难看:

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

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

我认为实现它的唯一方法是使用类似“friend”的方法。诀窍是在
FirstState
中有私有值类,它只能通过
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); }
    ...
}

我想你不清楚自己在做什么。 你是说
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(); }
}

我认为这在“正常”的情况下是不可能的。但是您可以将
FirstState
移动到与
SuperState
相同的包中,并将
受保护的SuperState(long)
包设为私有。但这并不能阻止移动
SecondState
的可能性。@Bret哦,OP询问编译时或运行时错误。我同意编译时错误会更好。这是目前为止最好的答案。是的,它有点像一个位链——一个状态的构造函数(在层次结构的每一层)可能需要从上一个状态的顶层复制(和修改)数据。施工后没有链条。两种状态越相似(共同的超类越多),传播的数据就越多。这不是我想要的,而是最好的可用选项,因为Java没有
friend
。如果是friend用例,那么应该使用friend模拟模式:。我在回答的开头提出的建议是,您应该让它更清楚,至少对您自己更清楚,这是您需要的抽象概念,然后根据它确定一个实现。
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(); }
}