4

我正在实现 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);
        }
    } 
}
4

5 回答 5

3

您通常会违反 SOLID 原则的“D”:

依赖倒置原则

该原则规定:

A. 高级模块不应该依赖于低级模块。两者都应该依赖于抽象。B. 抽象不应依赖于细节。细节应该取决于抽象。

实际上,您的构造函数实例化了一个具体的类:它本身 => 不够灵活且难以测试。(模拟的递归?:))

于 2013-04-02T20:02:45.997 回答
2

我想不出一个可以被认为是不好的做法的案例。

构造函数旨在完全构建一个类的实例,所以如果需要递归,使用它并没有错。

但是,为了清楚起见,您可能希望保留一个简单的构造函数并在另一个(私有)方法中实现递归......但这取决于您。当然,如果你把递归放在另一个方法中,你可以从你的构造函数中调用它。结果是一样的,但代码可能看起来更干净、更清晰。

于 2013-04-02T19:40:08.803 回答
1

通常,可能会建议反对在构造函数中执行资源密集型工作。

如何将“构造函数”与“构建整棵树”分开?

另外,你打算有子类吗?

于 2013-04-02T19:39:59.187 回答
0

构造函数是您生成对象的地方。它应该简单直接。

如果您需要使用一些值初始化对象 - 将这些值的计算外部化。

据我了解,从构造函数调用方法是一种不好的做法。我会使用一个委托类,它封装了所有逻辑。

将所有复杂的逻辑放在一个单独的服务类中(但同样 - 不是在构造函数中)并使用 - 将所有计算委托给该服务类。

构造函数对于保存复杂(包括递归)逻辑来说太敏感了。

于 2013-04-02T19:41:38.573 回答
0

如果你要子类化这个类——那么递归会给你带来很多痛苦,因为你将无法覆盖这个构造函数,以便创建子类的实例。

于 2013-04-02T19:42:57.160 回答