I just wrote a rather lengthy reply to a Programmers StackExchange question which I’d summarize as “why are the types and or methods I want to extend often sealed in common Java and .NET frameworks and libraries?” Its actually titled “Why shouldn’t classes be designed to be ‘open’?’”
My reply is here:
Because they don’t know any better.
The original authors are probably clinging to a misunderstanding of SOLID principles which originated in a confused and complicated C++ world.
I hope you will notice that the ruby, python, and perl worlds don’t have the problems that the answers here claim to be the reason for sealing. Note that its orthogonal to dynamic typing. Access modifiers are easy to work in most (all?) languages. C++ fields can be mucked with by casting to some other type (C++ is more weak). Java and C# can use reflection. Access modifiers make things just difficult enough to prevent you from doing it unless you REALLY want to.
Sealing classes and marking any members private explicitly violates the principle that simple things should be simple and hard things should be possible. Suddenly things that should be simple, aren’t.
I’d encourage you to try to understand the viewpoint of the original authors. Much of it is from an academic idea of encapsulation that has never demonstrated absolute success in the real world. I’ve never seen a framework or library where some developer somewhere didn’t wish it worked slightly differently and didn’t have good reason to change it. There are two possibilities that may have plagued the original software developers which sealed and made members private.
1. Arrogance – they really did believe they were open for extension and closed for modification
2. Complacence – they knew there might be other use cases but decided not to write for those use cases
I think in the corporate framework world, #2 is probably the case. Those C++, Java and .NET frameworks have to be "done" and they have to follow certain guidelines. Those guidelines usually mean sealed types unless the type was explicitly designed as part of a type hierarchy and private members for many things which might be useful for others use.. but since they don’t directly relate to that class, they aren’t exposed. Extracting a new type would be too expensive to support, document, etc…
The entire idea behind access modifiers is that programmers should be protected from themselves. "C programming is bad because it lets you shoot yourself in the foot." It is not a philosophy that I agree with as a programmer.
I much prefer python’s name mangling approach. You can easily (much easier than reflection) replace privates if you need. A great write up on it is available here: http://bytebaker.com/2009/03/31/python-properties-vs-java-access-modifiers/
Ruby’s private modifier is actually more like protected in C# and doesn’t have a private as C# modifier. Protected is a little different. There is great explanation here: http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/
Remember, your static language doesn’t have to conform to the antiquated styles of the code written in that language past.
(As also posted to http://simoncropp.posterous.com/make-everything-public)
I disagree strongly.
Yes, callers can circumvent access control via reflection – but then they’re *knowingly* messing with something that they obviously shouldn’t.
I should be able to change my implementation details without breaking callers. If they’ve deliberately messed around with reflection, that’s their own fault – but I take responsibility for keeping my public API stable. This isn’t a matter of what’s advanced and what’s not – it’s a matter of what’s meant to be relied on and what isn’t.
@jon
I agree with all of your points, but my agreements are orthogonal to my original points.
The crux of my point is that these .NET and C# idioms needs to change.
In python, yes, callers of “privates” know that they are messing with something that they shouldn’t by naming convention. Its far easier than using reflection.
The key is that the value added by this ease is greater than the value added by making it difficult using the private keyword. For evidence, see python and ruby.
By following this convention you can still change your implementation details without breaking callers. If they have deliberately used something with private naming convention, that is still their own fault. You can still take responsibility for keeping your own public API (and ABI) stable.
It is a matter of, “Simple things should be simple. Hard things should be possible”
If it isn’t clear yet, I am not advocating for everything public and that is all. I’m advocating for everything public with a convention (or maybe even interface) based approach to defining the public API. The private API should still be there for all the uses the original developer never considered. The consuming developer knows that “there be dragons.”
I’m afraid I still disagree – I’d rather use a compiler than conventions. Simple things are simple – a small visible API which only shows you things you *should* do, and *bad* things (taking dependencies on implementation details) are hard but feasible via reflection. I think the hardness reflects the extent to which I think such things should be strongly discouraged.
I would think it’s likely that if members that are “marked” private are not shown in Intellisense by default, 99% of developers would never know the difference anyway.