如何“拒绝”实例化一个类

问题描述:

例如,如何“拒绝”实例化一个类

public class Test { 
    Test() { 
    if(xxx)//do some check here 
     //reject instancing class test. 
    } 
} 

我想我可以抛出一个异常拒绝它,是有没有其他办法? 我不知道是什么的实例化被否决的影响,但我认为一个自然的方法是:

Test test = new Test();//return null here indicating instancing rejected. 

我希望Java和C++都应该有这种“拒绝”功能。

+0

¤C++非常灵活,可以让您轻松定义这样的特征,作为[NOXNEW](简写为“no exception'new'”)的宏,如[我在此处显示](http://codepad.org/0jADRP8O)。我认为Java也是如此,但以某种不同的方式实现。但是,请注意通过这样做 - 返回nullpointer - 您将丢弃任何异常信息,这在某些情况下非常不合需要。然而,大概在这种情况下,你根本就不会这样做。但值得注意的是。 Cheers&hth。, – 2012-02-16 05:44:30

+0

注意:在上面的答案中,我使用一个宏来传递可变数字参数,因为Visual C++ 10.0(当前版本)尚不支持可变参数模板,并且据我所知,它们将在Visual C++ 11中也不存在。对于完整的标准C++ 11来说,宏不是必需的。就此而言,借助一些图书馆支持,例如就像我在主博客上介绍的那样,C++ 03并不是必须的,尽管它使得更简单和更清晰的用法。干杯, – 2012-02-16 05:54:49

+0

另外,现在你让我思考了,我认为代码可以大大简化。这是简化工作。当你完成它时,你想知道原来的代码如何可能如此愚蠢复杂,但我只是直接给你,只需很少的工作。 :-) – 2012-02-16 05:57:16

有内置的语言没有这样的功能,但你必须实现它的两个标准方法:

  • 第一种是抛出异常。你在帖子中暗示了它。来电者需要预料到这个例外,并且准备好处理它。第二个是factory method。如果由于某种原因无法实例化您的类,它可能会返回null。您的呼叫者需要准备好处理来自工厂方法的空回报。

选择这两个选项并不容易。该指导原则是,如果拒绝实例化是例外情况,例如。编程或配置错误,然后转到异常路由。如果通常会发生拒绝,例如因为有些资源是暂时不可用,那么就去工厂方法路由。当然,这些规则也有例外,所以请使用您的最佳判断。

你不能从构造函数中返回null,但你可以(如你所建议的)抛出异常。

是的,如果您无法创建类的实例,则应该抛出异常。

如果你想返回null,你可以使用Factory pattern。例如。而不是Test test = new Test();您可以编写Test test = TestFactory.CreateTest();,并在TestFactory.CreateTest中执行您所需的所有检查。

new Test()总是返回一个非空实例Test(至少在Java中)。

+0

+1啊,很好的答案。 – 2012-02-16 04:58:41

我想我可以抛出一个异常拒绝

的确不错,从构造函数抛出异常将销毁所有子对象(如果使用继承)以及成员已经初始化。这是放弃构建对象的首选方法。

还有其他方法吗?

唯一的另一种方法是初始化为虚拟状态,并要求客户端代码检查构造函数是否使用特殊用途的方法成功运行。由于客户很容易忘记这种呼叫,我真的不推荐这种方法。

至于这个“解决方案”:

Test test = new Test();//return null here indicating instancing rejected. 

有没有办法强迫new从您的构造函数中返回一个空指针,所以这是行不通的。你可以模拟这种使用其他方法,如:

class Test 
{ 
    Test (...); // constructor that receives prepared arguments. 
public: 
    static Test * create (...) 
    { 
     // prepare arguments... 
     if (successful) { 
      return new Test(prepared_arguments); 
     } 
     return 0; 
    } 
}; 

,并使用该在你的代码:

Test * test = Test::create(...); 
if (!test) { 
    // handle error. 
} 

但你仍然可以忘记检查空指针。

首选的方法是抛出异常。它更简单,始终有效,并且需要更少的打字。

在C++中,你不neccessarily有一个指针返回,考虑:

Test t; // run the constructor 

因此,使用异常或工厂模式是唯一的方法来拒绝instanciation。