控制对象的实例化而不限制构造函数访问

时间:2013-08-13 17:21:07

标签: c#

当我们想要控制对象的实例化时,我们经常将构造函数设为私有或内部:

public class A {
    private A(int aParam) { }
}

然而,这与密封“A”类基本相同,因为现在没有人可以继承它。

因此,我们可以使构造函数受到保护:

public class A {
    protected A(int aParam) { }
}
public class B {
    protected B(int aParam) : base(aParam) { }
}

但是,这意味着来自B(或从中派生的任何类)的任何代码都可以实例化一个新的A.

我正在寻找一种控制实例化的方法,但不必将类密封(有效或其他方式)。

注意:我知道无论如何都可以使用反射和其他技巧来实例化类;我只对创建明确的“合同”感兴趣。如果有人想故意破坏我的合同,那就取决于他们。

3 个答案:

答案 0 :(得分:7)

  

我正在寻找一种控制实例化的方法,但不必将类密封(有效或其他方式)。

这在您的要求中确实是矛盾的。

如果要允许创建子类,则必须允许子类有效地创建父类,这意味着您至少需要一个protected构造函数。如果没有这个,子类就无法正确初始化实例。

通过将构造函数公开为受保护,您可以允许子类更改实例化规则(它们总是可以添加公共构造函数)。

这里只有两个选项:

  1. 使构造函数受到保护,并假设子类将执行“正确的操作”(无论您的方案中是什么),或
  2. 密封你的课程,然后展示你选择的构造方法。这可以防止子类,但不会阻止您的类通过组合而不是继承来重用。

答案 1 :(得分:1)

我不确定你的意思。如果没有错,那么您正试图阻止从Base Class Derived Class实例化protected吗?

这也是默认行为。当基类构造函数为class Program { A a = A.CreateInstance();//works B b = B.CreateInstanceOfB();//works A ab = B.CreateInstanceOfA();//wont work } public class A { protected A() { } public static A CreateInstance() { return new A(); } } public class B : A { protected B() : base()// { } public static B CreateInstanceOfB() { return new B(); } public static A CreateInstanceOfA() { return new A();//This wont compile CS1540: Cannot access protected member... } } 时,您无法从派生类实例化基类。

{{1}}

受保护的构造函数仅用于通过构造函数链接(使用base关键字)进行调用。没有反射就无法实例化它。

希望这有帮助。

答案 2 :(得分:0)

如果您希望能够实例化子类,但禁止显式实例化基类,那么您有两个选择:

  • 添加一个纯虚方法,从而使基类成为抽象。

  • 添加一个受保护的构造函数,并重载“new”运算符以禁止显式实例化基类,即使它不是抽象的。