'PIMPL Patterns in "high-level" languages - Possible/Applicable?
In the C++ world, there are two well-known strategies for maintaining binary compatibility with a library:
- Interfaces: all public classes are "interface" classes (only pure virtual methods, no members), which are implemented by private subclasses in the library
- PIMPL pattern: all public classes hold a single member which is a pointer to a forward-declared class, whose definition is private to the library
Both of these achieve binary stability, but #1 comes with some major disadvantages. The primary one, I believe, is that in the library, methods that accept instances of the public interface classes almost always must immediately force-downcast them to the private implementation classes. The use of interfaces incorrectly signals to clients that they are free to supply their own implementations of these interfaces, which if they ever do, will immediately fail on one of these force-downcasts. Unless polymorphism is the goal, the use of interfaces is arguably the wrong design.
Now let's consider "high-level" languages like Java, Kotlin, C# and Swift (and maybe even Typescript and Ruby). We can certainly adopt strategy #1. However this strategy suffers from the same concerns mentioned above.
But what about the PIMPL pattern? There's no such thing as "forward declaration" in these languages, but we can't even separate the class definition and implementation into different files. The compiler does this for us when it creates the package. So does an analogous pattern exist in these languages that "hides" the private details in the sense that it lets us freely modify private details without breaking binary compatibility?
Which leads to the next question...
Is it even necessary to begin with to "hide" class innards to achieve binary stability in those languages? This is necessary in C++ because of its on-stack value semantics, which makes compiled client code sensitive to the memory size of the library's classes. But to my knowledge, class instances in the "high-level" languages aren't moved around on the call stack, and instead work more like pointers/references would in C++, which may render the concern moot. If that's true, we can simply write classes "naively", and be sure that the binary compatibility remains stable as long as we don't mess with public methods/members. We could, however, do whatever we wish with private members, even if it entails changing the memory size of the public classes, and it wouldn't force client code to be recompiled.
So, in summary: are PIMPL patterns possible in these languages, or does the concept not even apply because there's no problem of private details "leaking" into the binary interface to begin with?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
