3

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

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。

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

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

4

3 回答 3

7

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

这与您的要求确实矛盾。

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

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

这里实际上只有两个选择:

  1. 使构造函数受到保护,并假设子类将做“正确的事情”(无论您的场景是什么),或者
  2. 密封你的类,然后暴露你选择的构造方法。这可以防止子类,但不会阻止您的类通过组合而不是继承被重用。
于 2013-08-13T17:28:32.477 回答
1

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

这也是默认行为。当您的基类构造函数是时,您不能从派生类实例化基类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...
    }
}

受保护的构造函数旨在仅通过构造函数链接(使用 base 关键字)调用。你不能在没有反射的情况下实例化它。

希望这可以帮助。

于 2013-08-13T18:57:22.300 回答
0

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

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

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

于 2013-08-13T18:07:17.013 回答