问题的本质是,给定这样的类层次结构:
class A
{
protected void MethodToExpose()
{}
protected void MethodToHide(object param)
{}
}
class B : A
{
new private void MethodToHide(object param)
{}
protected void NewMethodInB()
{}
}
class C : B
{
public void DoSomething()
{
base.MethodToHide("the parameter"); // This still calls A.MethodToHide()
base.MethodToExpose(); // This calls A.MethodToExpose(), but that's ok
base.NewMethodInB();
}
}
如何防止从类“B”继承的任何类看到方法A.MethodToHide()
?在C ++中,使用class B : private A
之类的声明很容易,但这种语法在C#中无效。
对于那些感兴趣的人(或者想知道我想要做什么),我们要做的就是为Rhino.Commons.NHRepository创建一个包装器来隐藏我们不知道的方法我想向我们的开发人员群体展示,因此我们可以采用千篇一律的方式开发我们的应用程序,新开发人员可以轻松地遵循这些方式。所以是的,我相信“Is-A”测试对整个链(WidgetRepository Is-A BaseRepository Is-A NHRepository)都有效。
编辑:为了论证,我应该提到,A类是我们无法控制的API类。否则问题变得相当容易。
答案 0 :(得分:21)
您无法执行此操作并保留层次结构。如果可能,您应该创建定义理想的接口,然后创建基类的子类并实现接口。在代码中仅引用接口(而不是基类类型)。
Adapter pattern专门用于解决当API未按照您的需求排列时如何使用框架的问题。
答案 1 :(得分:19)
已过时
在B类中,覆盖MethodToHide并添加Obsolete属性
[Obsolete("Reason", true)] // true will cause a compile-time error
设置EditorBrowsable
(如前所述)
在B类中,重写MethodToHide并添加EditorBrowsable属性
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
抛出异常
(如前所述)
在B类中,重写MethodToHide并抛出异常。
创建包装
我认为Michael Meadows是对的。使用Adapter pattern。此模式还允许在单元测试时更轻松地模拟代码。
class B: IInterface
{
protected void MethodToExpose()
{
A a = new A();
a.MethodToExpose();
}
protected void NewMethodInB()
{
}
}
答案 2 :(得分:14)
如果你想自定义一套功能,我会说你想制作一个包装而不是继承这个功能。我不知道如何在C#中做你想做的事。
考虑一下,如果你控制之外的某些代码需要这个NHRepository
实例,那该怎么办...但是你已经从你的子类中需要的函数中删除了这个函数(你会发送它,因为这是你唯一的NHRepository
实例。)一切都在蓬勃发展。这就是为什么我认为如果没有一些丑陋的黑客,我甚至不可能做到这一点。
答案 3 :(得分:6)
如果您使用的是Visual Studio,则可以使用以下属性隐藏intelliprompt中的方法/属性:
class A
{
protected void MethodToExpose()
{}
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
protected void MethodToHide(object param)
{}
}
它实际上并没有摆脱这个功能,但如果它们只是你的内部人。它可能足够接近。
答案 4 :(得分:4)
在我看来,最好的方法是,如果你只想隐藏而不是真正覆盖和外化新的功能,只需要添加一个EditorBrowsableState属性。 它隐藏了visual studio编辑器中的方法。谁将尝试使用它将最终导致编译时错误。
只需在方法上添加此代码:
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
例如
public class User
{
public void DoSomething()
{
Something...
}
}
public class Manager
{
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
public override void DoSomething()
{ }
}
void main()
{
User user = new User();
user.DoSomething();
Manager manager = new Manager();
manager.DoSomething(); // --------- This row will throw a design time error
}
祝你好运:)
答案 5 :(得分:1)
C#没有类似于C ++中的受保护或私有继承的概念。
您最好的选择是聚合该类的实例,并公开您感兴趣的消费者可以访问的方法集。
虽然在您的情况下我认为不可能,但您可以考虑创建一个接口,该接口只公开您希望消费者使用的常用功能,以便您的包装器在某些情况下可以替代它的聚合。 / p>
答案 6 :(得分:1)
虽然我对C ++知之甚少,但我从来不知道你能用C ++做到这一点。我担心我同意Blixt认为包装类可能就是我实现它的方式。
它可能有用(但我不确定)只需覆盖函数并在调用时抛出异常....
答案 7 :(得分:1)
据我所知,你不能以你想要的方式隐藏它。我认为你可以阻止它以任何实际的方式使用:
class B : A
{
public new void MethodToHide(object param)
{
throw new DontUseThisMethodException();
}
protected void NewMethodInB()
{}
}
不是最好的事情,所以你可能想以其他方式解决它......
答案 8 :(得分:1)
实际上,如果您将B的方法定义为可从C访问,则可以隐藏A的方法。
您的代码唯一的问题是您在隐藏声明中使用“私人”...如果您使用受保护或公开,您将不会遇到任何问题,它将按预期运行。我一直用田地做这件事。
答案 9 :(得分:0)
派生类B中的代码不会隐藏所有派生类型的基本方法,只能隐藏自身。您必须在基础中将方法设置为私有。解决此问题的唯一方法是创建另一个不公开此方法的基类。