抽象类设计:为什么不定义公共构造函数?
看这里(抽象类设计):http://msdn.microsoft.com/en -us/library/ms229047.aspx
它说:
(1) 不要在抽象类型中定义公共或受保护的内部(Visual Basic 中的受保护朋友)构造函数。
在 C# 中,我们不是能够实例化抽象类。那么,在 C# 中为抽象类定义公共构造函数还重要吗?或者因为语义的原因而不为抽象类编写公共构造函数?
它还说:
(2) 在抽象类中定义受保护的或内部构造函数。
定义内部构造函数?在(1)中,它告诉我们不定义内部受保护的构造函数是因为“具有公共或受保护内部可见性的构造函数适用于可以实例化的类型”。为抽象类定义内部构造函数不会违反 (1) 中的规则吗?
提前致谢。 :)
Look here (Abstract Class Design): http://msdn.microsoft.com/en-us/library/ms229047.aspx
It says:
(1) Do not define public or protected internal (Protected Friend in Visual Basic) constructors in abstract types.
In C#, we are not able to instantiate an abstract class. So, does it still matter to define public constructors for abstract classes in C# ? Or not writing public constructors for abstract classes because of semantic meaning?
It also says:
(2) Do define a protected or an internal constructor in abstract classes.
Define internal constructors ?? In (1), it tells us that not defining internal protected constructors is because that "Constructors with public or protected internal visibility are for types that can be instantiated". Doesn't defining internal constructors for abstract classes break the rules in (1) ?
Thanks in advance. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
让我们看一下每个案例。
推荐:
受保护 - 最明显的情况 - 所有子类都可以调用构造函数,无论它们驻留在哪个程序集中(只要抽象基类本身 对他们可见)。
内部 - 当您希望抽象类型公开可见,但不能公开继承时很有用。在这种情况下,您可能希望将所有非私有构造函数设为
内部
。只有与抽象基类相同的程序集中的子类才能调用构造函数 - 实际上,只有它们才能继承。另一个用例是,如果您想要一个仅对同一程序集子类可见的“特殊”构造函数。private - 主要用于“脏工作”构造函数,当抽象类使用构造函数链接时,这些构造函数将成为抽象类的其他构造函数的目标。当所有构造函数都是私有的时,唯一的其他用途是仅允许嵌套类进行子类化,这些类确实可以访问包含类型的私有成员。 p>
不推荐:
公共 - 没有用,其行为与
受保护
相同。无论如何,只有子类可以调用构造函数,因为基类是抽象的。受保护的内部 - 这也与
受保护的
没有什么不同。受保护的内部
可访问性级别意味着受保护或内部,而不是受保护和内部。但是,这里的internal
修饰符没有任何作用 - 它不会阻止位于程序集外部的子类调用构造函数(假设抽象基类是公共的),因为它们可以依赖protected
访问,也不允许非子类的相同程序集类型调用它(类型是抽象的)。这里的关键点是,抽象类中的每个非
私有
构造函数都已经充其量受到保护
。普通的internal
修饰符加强了对谁可以调用构造函数的限制。public
和protected inside
没有完成任何事情,因为它们似乎削弱了限制,但实际上并没有成功。Let's look at each of the cases.
Recommended:
protected - The most obvious case - all subclasses can call the constructor, irrespective of which assembly they reside in (as long as the the abstract base-class itself is visible to them).
internal - Useful when you want the abstract type to be publicly visible, but not publicly inheritable. In this case, you would want to make all of the non-private constructors
internal
. Only subclasses within the same assembly as the abstract base-class would be able to call the constructors - effectively, only they would be able to inherit. Another use-case would be if you wanted a 'special' constructor that should only be visible to same-assembly subclasses.private - Used mainly for 'dirty-work' constructors that are targeted by other constructors of the abstract class when it uses constructor-chaining. The only other use, when all the constructors are private, is to only allow subclassing by nested classes, which do have access to private members of the containing-type.
Not recommended:
public - Not useful, behaves identically to
protected
. Only subclasses can call the constructor anyway, since the base-class is abstract.protected internal - This too is no different from
protected
. Theprotected internal
accessibility level means protected OR internal, not protected AND internal. However, theinternal
modifier here serves no purpose - it doesn't prevent subclasses residing outside the assembly from calling the constructor (assuming the abstract base-class is public) since they can rely onprotected
access, nor does it allow same-assembly types that are not subclasses from calling it (the type is abstract).The key point here is that every non-
private
constructor in an abstract class is already at bestprotected
. The vanillainternal
-modifier strengthens restrictions on who can call the constructor.public
andprotected internal
don't accomplish anything because they appear to weaken restrictions, but don't really succeed in doing so.在 C# 中,我们无法实例化抽象类。那么,在 C# 中为抽象类定义公共构造函数还重要吗?或者不为抽象类编写公共构造函数是因为语义意义?
正是如此。您不希望用户看到可访问的构造函数,但当他们调用它时,他们会收到编译错误。
定义内部构造函数?在(1)中,它告诉我们不定义内部受保护的构造函数是因为“具有公共或受保护内部可见性的构造函数适用于可以实例化的类型”。为抽象类定义内部构造函数不会违反 (1) 中的规则吗?
我相信规则 1 是关于
public
的,而protected inside
规则 2 是关于 <代码>受保护和<代码>内部。所以两者之间没有交集。n C#, we are not able to instantiate an abstract class. So, does it still matter to define public constructors for abstract classes in C# ? Or not writing public constructors for abstract classes is because of the semantic meaning?
Exactly. You don't want the user to see an accessible constructor, but when they call it, they get a compile error.
Define internal constructors ?? In (1), it tells us that not defining internal protected constructors is because that "Constructors with public or protected internal visibility are for types that can be instantiated". Doesn't defining internal constructors for abstract classes break the rules in (1) ?
I believe rule 1 is about
public
andprotected internal
rule 2 is aboutprotected
andinternal
. So there's no intersection between the two.几年过去了。我想我现在对这个问题有了更好的理解。因此,除了阿尼的出色回答之外,我还想添加一些更多的意见。
这对编译器来说并不重要,但对代码阅读器来说很重要。抽象类型中的公共构造函数对代码读者来说是误导(他们可能认为它们可以被实例化)。
如果我们希望抽象类只能被同一个程序集中的子类继承,显然我们不能使用
protected
(否则可以在程序集外部继承)。现在我们有一些选项可供选择:public - 如上所述,
public
对代码阅读器来说是误导。不要使用它。private - 我们希望抽象类可由同一程序集中的子类继承,而不仅仅是嵌套子类,因此
private
不起作用。受保护的内部 - 我们永远不需要它,因为它与
受保护的
没有什么不同。内部 - 这对代码读者来说是误导,但我们别无选择。我认为这是一种权衡。
Years passed. I think I have better understanding of this question now. So I would like to add some more input besides Ani's excellent answer.
It doesn't matter to the compiler, but it does matter to code readers. Public constructors in abstract types is misleading to code readers (they might think they can be instantiated).
If we want the abstract class to be inheritable only by subclasses within the same assembly, obviously we cannot use
protected
(otherwise it can be inherited outside the assembly). Now we have some options to choose:public - As mentioned above,
public
is misleading to code readers. Don't use it.private - We want the abstract class to be inheritable by subclasses within the same assembly, not just by nested subclasses, so
private
won't work.protected internal - We'll never need it because it's no different from
protected
.internal - It is misleading to code readers, but we have no other choice. I would think it a trade-off.