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