在构造函数中使用递归是一个不好的做法吗?

4

我正在实现 van Emde Boas 树,遇到一个情况,在构造函数中使用递归非常有用。

当我在树中创建根节点时,该节点将指向许多其他节点,这些节点将指向许多其他节点,以此类推。即使它们用 null 数据初始化,我仍然希望它们都存在。

编辑:回应评论时,我认为这可能是不好的实践,因为我们在分配内存时总是需要小心。在这种情况下,用户可能没有意识到分配新的这样的节点可能会产生什么影响,因此他们可能分配比他们想要的更多的内存?除此之外,我认为在构造函数中分配内存似乎有些奇怪/危险。

该代码通过递归地创建新节点,直到整个树被创建。这是一种不好的实践吗?如果是,那么在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);
        }
    } 
}

2
你为什么认为这可能是一种不好的做法呢? - Robert Harvey
在你的位置上,我可能会保持构造函数非常基本,并将所有这些逻辑移动到静态工厂方法中,但这是一个风格判断调用。 - Louis Wasserman
我认为递归是在你的情况下非常合适的方法,无论是构造函数还是其他函数。 - skuntsel
你是否在寻找一个能够反映可能危险性的答案?我并没有看到任何明显的问题,只要你确实想要聚合数据。 - vinczemarton
@Eelke - 你有注意到这是一个Java问题吗?在Java中没有析构函数和内存释放,因此也就没有问题。 - JimmyB
5个回答

3
您通常违反了 SOLID 原则的 “D” 字条:
依赖倒置原则
该原则规定:
A. 高层模块不应该依赖于低层模块。两者都应该依赖于抽象。 B. 抽象不应该依赖于细节。细节应该依赖于抽象。
实际上,您的构造函数会实例化一个具体类:它本身 => 不够灵活且难以测试。(模拟的递归吗?:))

2
我想不出有哪种情况会认为这是不好的做法。
构造函数的目的是完全构建一个类的实例,因此如果需要递归,使用递归并没有错。
然而,为了清晰起见,您可能希望保留一个简单的构造函数,并在另一个(私有)方法中实现递归...但这取决于您。当然,如果您将递归放入另一个方法中,则可以从构造函数中调用它。结果是相同的,但代码可能看起来更干净、更清晰。

我同意将逻辑移动到init方法或工厂方法中会更好。好建议。 - Justin
1
请确保您不要从构造函数中传递任何对this的引用。 - Boris the Spider

1
一般来说,在构造函数中进行资源密集型操作可能不被建议。是否考虑将“构造函数”与“构建整个树”分开?此外,您计划有子类吗?

我不打算对此进行子类化。 - Justin

0

构造函数是一个你创建对象的地方。它应该简单明了。

如果您需要使用某些值来初始化对象,请将这些值的计算外部化。

据我所知,从构造函数调用方法是不好的做法。我会使用委托类来封装所有逻辑。

将所有复杂的逻辑放在单独的服务类中(但不要再构造函数中),并使用-将所有计算委派给该服务类。

构造函数是保存复杂(包括递归)逻辑的过于敏感的地方。


0

如果您要派生这个类,那么递归将会给您带来很多痛苦,因为您无法重写此构造函数以创建子类的实例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接