Reputation: 27700
Does C# have the notion of private / protected inheritance, and if not, why?
C++
class Foo : private Bar {
public:
...
};
C#
public abstract NServlet class : private System.Web.UI.Page
{
// error "type expected"
}
I am implementing a "servlet like" concept in an .aspx page and I don't want the concrete class to have the ability to see the internals of the System.Web.UI.Page base.
Upvotes: 49
Views: 41658
Reputation: 2302
@bdukes: Keep in mind that you aren't truly hiding the member. E.g.:
class Base
{
public void F() {}
}
class Derived : Base
{
new private void F() {}
}
Base o = new Derived();
o.F(); // works
But this accomplishes the same as private inheritance in C++, which is what the questioner wanted.
Upvotes: 2
Reputation: 2214
First solution:
protected internal acts as public in the same assembly and protected on other assemblies.
You would need to change the access modifier of each members of the class which are not to be exposed through inheritance.
It is a bit restrictive though that this solution requires and forces the class to be inherited to be used by another assembly. Thus the choice of being used only by inheritance or not is taken by the unknowing parent... normally the children are more knowing of the architecture...
Not a perfect solution but might be a better alternative to adding an interface to hide methods and still leaving the possibility of using the parent methods to be hidden though the child class because you might not easily be able to force the use of the interface.
Problem:
The protected and private access modifiers cannot be used for methods that are implementing interfaces. That means that the protected internal solution cannot be used for interface implemented methods. This is a big restriction.
Final solution:
I fell back to the interface solution to hide methods.
The problem with it was to be able to force the use of the interface so that members to be hidden are ALWAYS hidden and then definitely avoiding mistakes.
To force using only the interface, just make the constructors protected and add a static method for construction (I named it New). This static New method is in fact a factory function and it returns the interface. So the rest of the code has to use the interface only!
Upvotes: 1
Reputation: 9287
C# allows public inheritance only. C++ allowed all three kinds. Public inheritance implied an "IS-A" type of relationship, and private inheritance implied a "Is-Implemented-In-Terms-Of" kind of relationship. Since layering (or composition) accomplished this in an arguably simpler fashion, private inheritance was only used when absolutely required by protected members or virtual functions required it - according to Scott Meyers in Effective C++, Item 42.
My guess would be that the authors of C# did not feel this additional method of implementing one class in terms of another was necessary.
Upvotes: 23
Reputation: 1500
I know this is an old question, but I've run into this issue several times while writing C#, and I want to know...why not just use an interface?
When you create your subclass of the 3rd party framework's class, also have it implement a public interface. Then define that interface to include only the methods that you want the client to access. Then, when the client requests an instance of that class, give them an instance of that interface instead.
That seems to be the C#-accepted way of doing these sorts of things.
The first time I did this was when I realized that the C# standard library didn't have a read-only variant of a dictionary. I wanted to provide access to a dictionary, but didn't want to give the client the ability to change items in the dictionary. So I defined a "class DictionaryEx<K,V,IV> : Dictionary<K,V>, IReadOnlyDictionary<K,IV> where V : IV" where K is the key type, V is the real value type, and IV is an interface to the V type that prevents changes. The implementation of DictionaryEx was mostly straightforward; the only difficult part was creating a ReadOnlyEnumerator class, but even that didn't take very long.
The only drawback I can see to this approach is if the client tries to dynamically cast your public interface to the related subclass. To stop this, make your class internal. If your client casts your public interface to the original base class, I think it'd be pretty clear to them that they're taking their life in their own hands. :-)
Upvotes: 1
Reputation: 1826
No it doesn't. What would the benefit be of allowing this type of restriction?
Private and protected inheritance is good for encapsulation (information hiding). Protected* inheritance is supported in C++, although it isn’t in Java. Here’s an example from my project where it would be useful.
There is a base class in as 3rd party framework**. It has dozens of settings plus properties and methods for manipulating them. The base class doesn’t make a lot of checking when individual settings are assigned, but it will generate an exception later if it encounters an unacceptable combination.
I’m making a child class with methods for assigning these settings (e.g. example, assigning carefully crafted settings from a file). It would be nice to deny the rest of the code (outside my child class) the ability to manipulate individual settings and mess them up.
That said, I think in C++ (which, again, supports private and protected inheritance) it's possible to cast the child class up to parent and get access to parent's public members. (See also Chris Karcher's post) Still, protected inheritance improves information hiding. If members of a class B1 need to be truly hidden within other classes C1 and C2, it can be arranged by making a protected variable of a class B1 within C1 and C2. Protected instance of B1 will be available to children of C1 and C2. Of course, this approach by itself doesn't provide polymorphism between C1 and C2. But polymorphism can be added (if desired) by inheriting C1 and C2 from a common interface I1.
*** For brevity will use "protected" instead of "private and protected".
** National Instruments Measurement Studio in my case.
Upvotes: 9
Reputation: 1083
If you want the NServlet class to not know anything about the Page, you should look into using the Adapter pattern. Write a page that will host an instance of the NServlet class. Depending on what exactly you're doing, you could then write a wide array of classes that only know about the base class NServlet without having to pollute your API with asp.net page members.
Upvotes: 3
Reputation: 156005
You can hide inherited APIs from being publicly visible by declaring that same member in your class as private, and using the new keyword. See Hiding through Inheritance from MSDN.
Upvotes: 5
Reputation: 42516
No it doesn't. What would the benefit be of allowing this type of restriction?
Upvotes: -3
Reputation: 70344
You probably want a ServletContainer class that gets hooked up with a NServlet implementation. In my book, not allowing private / protected inheritance is not really a big deal and keeps the language less confusing - with LINQ etc. we allready have enough stuff to remember.
Upvotes: 1