当我们想要控制对象的实例化时,我们经常将构造函数设为私有或内部:
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.
我正在寻找一种控制实例化的方法,但不必将类密封(有效或其他方式)。
注意:我知道无论如何都可以使用反射和其他技巧来实例化类;我只对创建明确的“合同”感兴趣。如果有人想故意破坏我的合同,那就取决于他们。
答案 0 :(得分:7)
我正在寻找一种控制实例化的方法,但不必将类密封(有效或其他方式)。
这在您的要求中确实是矛盾的。
如果要允许创建子类,则必须允许子类有效地创建父类,这意味着您至少需要一个protected
构造函数。如果没有这个,子类就无法正确初始化实例。
通过将构造函数公开为受保护,您可以允许子类更改实例化规则(它们总是可以添加公共构造函数)。
这里只有两个选项:
答案 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”运算符以禁止显式实例化基类,即使它不是抽象的。