and that's the rub because I cannot abide using a black box and not knowing what's going on |
The reason why the implementation is hidden is because it allows it to be flexible. If outside source needs to know what the code is doing, then it can only use 1 kind of object. On the other hand, if the interface is abstracted, the same code can be used with
an infinite number of objects, as long as those objects share a common interface.
As an example, I'm working on a library which abstracts pretty much everything. One of the simpler examples is a HashBase class I made, which simply has a "Hash" pure virtual functions. Derived from this class would be classes which do things like MD5, CRC32, etc. Because the interface is abstracted, and the internal workings hidden, outside code can simply call
myhash->Hash(foo,bar);
and the appropriate calculations can be performed. The code need not know what calculations it's actually doing.
Another example would be to abstract something like a File or Stream (which is sort of already done in C++ and even in C's stdio). Code can read from a source without needing to know exactly where the data is coming from. Is it a file on the disk? Is it user input? Is it from a block of memory? Is it from a chunk of compressed data that's being decompressed on the fly? It doesn't matter -- if the interface is abstracted, the code for all is the same.
Another more complciated example of something I'm working on is an abstracted FileSystem class, with things like CreateDirectory, OpenFile, etc, etc. Benefits to making this abstracted are twofold:
1) Platform specific methods can be isolated (ie: the FileSystem class can be rewritten for multiple platforms, but code elsewhere in the program doesn't care what platform it's on because FileSystem has the same interface regardless)
2) More complex things can be abstracted as a simple file system... like say... a .zip file or some other kind of archive. Code can open and modify files, create directories and whatnot with a FileSystem pointer, totally oblivious to the fact that it's actually modifying a .zip file.
It just makes it so much easier to separate
what you're doing from
how you're doing it. Because the what never changes, but the how can change greatly depending on the circumstances. This is why OO and abstraction are so important/useful.
Also ... if you are manipulating "protected" data members directly relying on the fact that you know how the underlying implementation works - what happens if the implementation needs to change (new feature added or somesuch). All of that code now falls apart and you have to redo everything.