我知道这是一个坏主意,它会导致错误。问题是,我需要"打算"行为。
"低":
// simplified example
abstract class Low {
String name;
public Low(String name) {
this.name = name;
}
public Low(int id) {
this.name = getNameForId(id);
}
public Low() {} // will be loaded later
@Override
public String toString()
{
return name;
}
public void load(InputStream in) {
// --- grab ID from stream ---
this.name = getNameForId(id);
}
protected abstract String getNameForId(int id);
}
和"高":
class High extends Low {
public High(int id) { super(id); }
public High(String name) { super(name); }
public High() {} // will be loaded later
@Override
protected String getNameForId(int id)
{
return Registry.getName(id);
}
}
请注意,在这种特殊情况下,它会正常工作。但是,一旦最重要的方法需要使用某些字段,它就会崩溃。
如何做得更好?
答案 0 :(得分:1)
您可以通过添加public void load(int id)
方法(就像对InputStream一样)并删除Constructor(int id)
来避免调用抽象方法。
您可能希望添加一些Factory功能,以确保在没有正确名称值的情况下永远无法访问构造的实例。
答案 1 :(得分:1)
您想要从Low和High对象中分离出ID的名称。引入一个用于加载ID的接口的接口。
public interface NameProvider
{
String getNameForId(String id);
}
为每个名称来源添加特定的实现。
public class InputStreamNameProvider implements NameProvider
{
private InputStream inputStream;
// Constructor
public String getNameForId(String id)
{
// return name loaded via inputStream
}
}
public class RegistryNameProvider implements NameProvider
{
public String getNameForId(String id)
{
return Registry.getName(id);
}
}
然后,您可以向Low添加一个新构造函数,该构造函数将NameProvider和String id作为参数
public Low(NameProvider provider, String id)
{
this(provider.getNameForId(id));
}
甚至在构造Low或High实例之前使用名称提供程序。主要思想是分离从低和高对象加载ID的名称。