问题
The essence of the problem is, given a class hierarchy like this:
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();
}
}
How can I prevent any classes that inherit from class "B" from seeing the method A.MethodToHide()
? In C++, this was easy enough by using a declaration such as class B : private A
, but this syntax is not valid in C#.
For those interested (or wondering what I'm really trying to do), what we're trying to do is create a wrapper for for Rhino.Commons.NHRepository that hides the methods we don't want to expose to our group of developers, so we can have a cookie-cutter way of developing our app that new developers can easily follow. So yes, I believe the "Is-A" test is valid for the whole chain (WidgetRepository Is-A BaseRepository Is-A NHRepository).
Edit: I should have mentioned, for the sake of argument, that class A is an API class outside of our control. Otherwise the problem gets considerably easier.
回答1:
You can't do it and preserve the hierarchy. If possible, you should create interfaces that define your ideal, then subclass the bases classes and implement the interfaces. reference the interfaces only (not the base class types) in your code.
The Adapter pattern was created specifically to solve the problem of how to use a framework when its API doesn't line up exactly with your needs.
回答2:
Obsolete It
In class B, override MethodToHide and add the Obsolete attribute
[Obsolete("Reason", true)] // true will cause a compile-time error
Set EditorBrowsable
(As mentioned previously)
In class B, override MethodToHide and add the EditorBrowsable attribute
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
Throw exception
(As mentioned previously)
In class B, override MethodToHide and throw exception.
Create Wrapper
I think Michael Meadows is right. Use the Adapter pattern. This pattern also allows easier mocking of code when unit testing.
class B: IInterface
{
protected void MethodToExpose()
{
A a = new A();
a.MethodToExpose();
}
protected void NewMethodInB()
{
}
}
回答3:
If you want to custom tailor a set of features, I'd say you want to make a wrapper rather than inherit the functionality. I don't know of a way to do what you want in C# either.
Think about it, what if some code outside your control wants this NHRepository
instance for something... but you've removed the functionality from the function it needs in your child class (which you would send in, since that's your only NHRepository
instance.) Everything goes boom. That's why I don't think it's even possible to do without some ugly hack.
回答4:
If you are using Visual Studio, you can hide the methods/properties from intelliprompt with this attribute:
class A
{
protected void MethodToExpose()
{}
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
protected void MethodToHide(object param)
{}
}
It won't actually get rid of the function, but if they are just your internal people. It might be close enough.
回答5:
In my opinion, the best way to do it, if you just want to hide and not really override and externalize a new functionallity, is just to add an EditorBrowsableState attribute. It hides the the method in the visual studio editor. Who ever will try to use it will end up with a compile time error.
Just add this code on top of your method:
[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
For example
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
}
Good Luck :)
回答6:
C# does not have a concept similar to protected or private inheritance in C++.
Your best option is to aggregate an instance of the class and expose the set of methods you are interested in you consumers having access to.
Although in your case I don't think it's possible, you could look into creating an interface that exposes just the common functionality that you want consumers be work with so that your wrapper can be substitutable in some instances for it's aggregate.
回答7:
I never knew you could do that in C++ though I don't know much about C++. I'm afraid that I agree with Blixt that a wrapper class is probably how I'd implement this.
It might work (but I'm not sure) to simply override the function and throw an exception upon a call....
回答8:
As far as I know you can't hide it in the way you want. I think you could prevent it from being used in any practical manner though:
class B : A
{
public new void MethodToHide(object param)
{
throw new DontUseThisMethodException();
}
protected void NewMethodInB()
{}
}
Not the nicest thing to do though, so you would probably want to solve it in some other way...
回答9:
Actually you CAN hide A's method from C if you would have defined B's method as accessible from C.
The only problem with your code is that you use "private" on your hiding declaration... if you use protected or public you would not have any issues and it would operate as you expect. I do this all the time with fields.
回答10:
Your code in derived class B won't hide the base method from all derived types, only itself. You would have to set the method to private in the base. The only way around this issue is to create another base class that does not expose this method.
来源:https://stackoverflow.com/questions/1125746/how-to-hide-remove-a-base-classs-methods-in-c