C#是否具有私有和受保护inheritance的概念?
C#是否拥有私有/受保护inheritance的概念,如果不是,为什么?
C ++
class Foo : private Bar { public: ... };
C#
public abstract NServlet class : private System.Web.UI.Page { // error "type expected" }
public abstract NServlet class : private System.Web.UI.Page { // error "type expected" }
我正在一个.aspx页面中实现一个“servlet like”的概念,我不希望具体的类能够看到System.Web.UI.Page基础的内部。
C#只允许公共inheritance。 C ++允许所有三种。 公共inheritance意味着一种“IS-A”types的关系,而私人inheritance则暗示着“是 – 在 – 条件 – 关系 – ”的关系。 由于分层(或合成)以一种可以说更简单的方式实现了这一点,所以私有inheritance只有在被保护的成员或虚函数所要求的时候才被使用 – 根据Scott Meyers的Effective C ++第42项。
我的猜测是,C#的作者不觉得这个额外的方法来实现一个类的另一个是必要的。
您可以通过将类中相同的成员声明为private,并使用new关键字将隐藏的API隐藏起来。 请参阅通过从MSDN inheritance隐藏 。
@bdukes:请记住,你并没有真正隐藏会员。 例如:
class Base { public void F() {} } class Derived: Base { new private void F() {} } Base o = new Derived(); oF(); // works
编辑:但是这完成一样的私人inheritance在C + +,这是提问者想要:)
不,不。 允许这种限制的好处是什么?
私有和受保护的inheritance有利于封装(信息隐藏)。 受保护的*inheritance在C ++中受支持,尽pipe它不在Java中。 这里是我的项目中的一个例子,它将是有用的。
在第三方框架中有一个基类**。 它有几十个设置,加上属性和操作方法。 基类在分配个别设置时不会进行大量的检查,但如果遇到不可接受的组合,它将在稍后生成exception。
我正在创build一个子类,用分配这些设置的方法(例如,从文件中分配精心devise的设置)。 如果我们不能在子类之外的其他代码中操作个别设置并将其搞乱,那将是很好的做法。
也就是说,我认为在C ++(它也支持私有和受保护的inheritance)的情况下,可以将子类强制转换为父类,并可以访问父类的公共成员。 (另见Chris Karcher的文章 )尽pipe如此,受保护的inheritance改善了信息隐藏。 如果一个B1类的成员需要真正隐藏在其他类C1和C2中,则可以通过在C1和C2内创build一个B1类的受保护variables来进行安排。 C1和C2的孩子可以使用受保护的B1实例。 当然,这种方法本身并不提供C1和C2之间的多态性。 但是可以通过从通用接口I1inheritanceC1和C2来添加多态性(如果需要的话)。
***为简洁起见,将使用“保护”而不是“私人和受保护”。
**国家仪器测量工作室在我的情况。
- 缺口
如果你想让NServlet类不知道页面的任何内容,你应该使用适配器模式。 编写一个将承载NServlet类实例的页面。 根据你在做什么,你可以写一大堆只知道基类NServlet的类,而不必用asp.net页面成员来污染你的API。
您可能需要一个ServletContainer类,它可以与NServlet实现联系起来。 在我的书中,不允许私有/受保护的inheritance并不是什么大问题,并且不会让语言变得混乱 – 对于LINQ等,我们已经有足够的东西来记住了。
不,只是公共inheritance。
我知道这是一个古老的问题,但我在编写C#时遇到过这个问题,我想知道…为什么不使用接口?
当你创build第三方框架类的子类时,也要实现一个公共接口。 然后定义该接口以仅包含您希望客户端访问的方法。 然后,当客户端请求该类的一个实例时,请给它们一个该接口的实例。
这似乎是C#接受的做这种事情的方式。
我第一次这样做的时候,我意识到C#标准库没有一个字典的只读变体。 我想提供字典的访问权限,但不想让客户端能够更改字典中的项目。 所以我定义了一个“类DictionaryEx <K,V,IV>:Dictionary <K,V>,IReadOnlyDictionary <K,IV>其中V:IV”其中K是键types,V是实数值types,IV是V型接口可以防止更改。 DictionaryEx的实现大多是直接的; 唯一困难的部分是创build一个ReadOnlyEnumerator类,但即使这样也不需要很长时间。
我可以看到这种方法的唯一缺点是,如果客户端试图dynamic地将您的公共接口转换为相关的子类。 要停止这个,让你的class级内部。 如果你的客户把你的公共接口转换到原来的基类,我认为他们很清楚他们将自己的生活掌握在自己的手中。 🙂
第一个scheme
保护在同一集会上公开的内部行为,并在其他集会上受到保护。
您将需要更改不会通过inheritance暴露的类的每个成员的访问修饰符。
虽然这个解决scheme需要强制类被inheritance以被另一个程序集使用,但是有点限制。 因此,只有通过inheritance才能使用的select是由不知情的父母来做的…通常孩子们对build筑更加了解…
不是一个完美的解决scheme,但可能是一个更好的替代scheme,添加一个接口来隐藏方法 ,仍然留下使用父类方法隐藏子类的可能性,因为你可能不能轻易地强制使用该接口。
问题:
受保护和专用访问修饰符不能用于实现 接口的方法 。 这意味着受保护的内部解决scheme不能用于接口实现的方法。 这是一个很大的限制。
最终解决scheme
我回到了界面解决scheme来隐藏方法 。
它的问题是能够强制使用界面,以便隐藏成员总是隐藏,然后肯定避免错误。
强制只使用接口 ,只是使构造函数受到保护,并添加一个静态方法施工 (我把它命名为New)。 这个静态New方法实际上是一个工厂函数,它返回接口 。 所以剩下的代码只能使用这个接口!
不,不。 允许这种限制的好处是什么?