我正在实现van Emde Boas树,我遇到过在构造函数中使用递归非常有用的情况。
当我在树中创建根节点时,该节点将具有指向许多其他节点的指针,并且这些节点将指向许多其他节点,依此类推。即使这些是使用空数据初始化的,我仍然希望它们全部存在。
编辑:在回答评论时,我认为这可能是不好的做法,因为在分配内存时我们总是需要小心。在这种情况下,用户可能不知道分配新的这样的节点可能具有的效果,因此他们可能会分配更多的内存然后他们打算?除此之外,我认为在构造函数中分配内存似乎很奇怪/危险。
代码以递归方式创建新节点,直到创建完整树。这是一种不好的做法吗?如果有,那么在Java中有更好的方法吗?
//Constructor
public VEBNode(int universeSize)
{
this.universeSize = universeSize;
min = vEBTree.NULL;
max = vEBTree.NULL;
if(universeSize <= 2)
{
summary = null;
cluster = null;
}
else
{
int childUnivereSize = (int)Math.sqrt(universeSize);
summary = new VEBNode(childUnivereSize);
cluster = new VEBNode[childUnivereSize];
for(int i = 0; i < childUnivereSize; i++)
{
cluster[i] = new VEBNode(childUnivereSize);
}
}
}
答案 0 :(得分:3)
您通常违反SOLID原则的“D”:
依赖性倒置原则
原则指出:
一个。高级模块不应该依赖 低级模块。两者都应该取决于抽象。 B.抽象 不应该依赖于细节。细节应该取决于 抽象。
实际上,你的构造函数实例化了一个具体的类:self =&gt;没有足够的灵活性和难以测试。 (模拟的递归?:))
答案 1 :(得分:2)
我无法想到一个可以被视为不良行为的案例。
构造函数是为了完全构建一个类的实例,所以如果需要递归,那么使用它是没有错的。
但是,为了清楚起见,您可能希望保留一个简单的构造函数并在另一个(私有)方法中实现递归......但这取决于您。当然,如果将递归放在另一个方法中,可以从构造函数中调用它。结果是一样的,但代码可能看起来更清晰,更清晰。
答案 2 :(得分:1)
通常,可能会建议在构造函数中执行资源密集型操作。
如何将“构造函数”与“构建整个树”分开?
另外,你打算有子类吗?
答案 3 :(得分:0)
构造函数是您生成对象的地方。它应该简单明了。
如果需要使用某些值初始化对象 - 外部化这些值的计算。
据我所知,从构造函数中调用方法是一种不好的做法。我使用了一个委托类,它封装了所有的逻辑。
将所有复杂的逻辑放在一个单独的服务类中(但是再次 - 不在构造函数中)并使用 - 将所有计算委托给该服务类。
构造函数太复杂了,无法容纳复杂的(包括递归)逻辑。
答案 4 :(得分:0)
如果你要继承这个类的子类 - 那么递归会给你带来很大的痛苦,因为你将无法覆盖这个构造函数,因此你创建了一个子类的实例。