C++
class Foo : private Bar {
public:
...
};
C#
public abstract class NServlet : private System.Web.UI.Page
{
// 错误:“需要类型”
}
我正在一个.aspx页面中实现类似servlet的概念,而且我不想让具体类能够看到System.Web.UI.Page基类的内部。
class Foo : private Bar {
public:
...
};
C#
public abstract class NServlet : private System.Web.UI.Page
{
// 错误:“需要类型”
}
我正在一个.aspx页面中实现类似servlet的概念,而且我不想让具体类能够看到System.Web.UI.Page基类的内部。
C#仅允许公共继承。C++允许所有三种类型的继承。公共继承意味着一种“IS-A”的关系,而私有继承则意味着一种“在某种程度上是通过实现实现的”关系。由于分层(或组合)可以以更简单的方式完成这一点,因此只有当需要受保护的成员或虚函数要求时,才会使用私有继承 - 根据Scott Meyers在Effective C++,条款42中的说法。
我的猜测是,C#的作者们并不认为这种实现一个类以另一个类为基础的额外方法是必要的。
static_cast<A>(b).f()
报错:"error: 'A' is an inaccessible base of 'B'"。 - jrsala您可以通过在您的类中声明相同成员为私有并使用新关键字来隐藏继承的API,使其不被公开可见。请参阅MSDN上的继承隐藏。
Dictionary<K,V>
,这也是很痛苦的。 - NetMage@bdukes: 请记住,您并没有真正隐藏该成员。例如:
class Base
{
public void F() {}
}
class Derived : Base
{
new private void F() {}
}
Base o = new Derived();
o.F(); // works
Base
的私有继承将不允许调用 o.F()
。 - NetMage第一种解决方案:
protected internal 在同一程序集中作为公共访问,而在其他程序集中作为受保护的访问。
您需要更改类的每个成员的访问修饰符,以便不通过继承暴露它们。
虽然这种解决方案有点限制,因为需要和强制该类被继承才能被另一个程序集使用。因此,选择仅通过继承或不通过继承使用是由不知情的父级来做出的...通常子类更了解架构...
这不是一个完美的解决方案,但可能是一个更好的替代方法,用于隐藏方法而不是添加接口,并仍然保留使用父方法被隐藏的可能性,因为您可能无法轻松地强制使用接口。
最终解决方案:
我选择了使用接口来隐藏方法的方案。
它的问题在于如何强制使用接口,以便要隐藏的成员始终处于隐藏状态,并最终避免错误。
为了强制仅使用接口,只需将构造函数设为受保护的,并添加一个静态方法用于构建(我将其命名为New)。这个静态的New方法实际上是一个工厂函数,它返回接口。因此,代码的其余部分必须仅使用接口!
不,只有公共继承。
我知道这是一个老问题,但在编写C#时我遇到了这个问题好几次,我想知道...为什么不使用接口呢?
当您创建第三方框架类的子类时,还要让它实现一个公共接口。然后定义该接口仅包括您希望客户端访问的方法。然后,当客户端请求该类的实例时,给他们一个该接口的实例。
这似乎是C#中做这些事情的一种被接受的方式。
我第一次这样做是当我意识到C#标准库没有字典的只读变体时。我想提供对字典的访问,但不想让客户端能够更改字典中的项目。因此,我定义了一个“class DictionaryEx<K,V,IV> : Dictionary<K,V>, IReadOnlyDictionary<K,IV> where V : IV”,其中K是键类型,V是实际值类型,IV是防止更改的V类型的接口。 DictionaryEx的实现大多是直截了当的;唯一困难的部分是创建一个ReadOnlyEnumerator类,但即使那也没有花费很长时间。
我能看到这种方法唯一的缺点是,如果客户端尝试将您的公共接口动态转换为相关的子类,则无法实现。为了防止这种情况发生,请将您的类设置为内部类。如果您的客户端将您的公共接口转换为原始基类,我认为他们会非常清楚地意识到自己在冒险。 :-)不,它不会。允许这种类型的限制有什么好处呢?
IHttpHandler
来实现类似于 Servlet 的概念呢? - Jordão