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(); }
}
我有一个抽象 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(); }
}