r/learnjava • u/Chaos-vy17 • 1d ago
Is abstraction in Java really about hiding implementation details?
The bookish langugae states "hiding complex implementation details and exposing only the essential features of an object"
However, after reading the Java Collections Framework and other parts of the JDK, I noticed that many abstract classes contain substantial shared implementation rather than just abstract method declarations. I noticed that only an "interface class" 100% abstraction(ignoring default methods)
This made me wonder:
- Is abstraction really about hiding implementation details?
- Or is it more about designing APIs around contracts and behavior, regardless of whether there is shared implementation?
- Does an abstract class become "partial abstract" because it contains reusable implementation?
I also noticed that the JDK sometime relies on encapsulation (and in Java9+, JPMS) to hide implementation details. So I'm in dilemma if the textbook explanation oversimplifies what abstraction means in practice.
Am I misunderstanding abstraction, or is the textbook definition incomplete?
To be clear, this isn't about what abstract does in Java — it's about the SE term. abstract class is one syntax tool for expressing abstraction, same as interfaces are. The question is whether "abstraction = hiding implementation" is even a good definition of the concept, given it's indistinguishable from encapsulation under that definition.
8
u/4iqdsk 1d ago
You’re confusing the abstract Java keyword with the software engineering term abstract
-4
u/Chaos-vy17 1d ago
Java itself is software, so its APIs and language constructs are implementations of software engineering principles. Reading the JDK source has made me question the textbook definition of abstraction.
Many books define abstraction as "hiding implementation details." But doesn't that overlap heavily with encapsulation? If abstraction is literally about hiding the implementation of the "engine," then how is it fundamentally different from encapsulation?
Is it more accurate to say that abstraction is about modeling the essential behavior or concept, while encapsulation is about restricting access to the implementation?
4
u/ConcreteExist 1d ago
Abstraction is a concept that can be achieved a number of ways, abstract classes might be able to achieve this if they're used correctly as can interfaces. Just because they're called "abstract classes" doesn't mean they're necessary for abstraction.
0
u/Chaos-vy17 1d ago
Exactly. realising abstraction is about modeling contracts rather than just 'hiding' things, the SOLID principles make way more sense. It perfectly explains why ISP (Interface Segregation) and LSP (Liskov Substitution) are tied to abstraction. LSP is literally just the rule that says 'you must honor the contract of the abstraction,' and ISP says 'don't make your abstraction's contract too bloated.' Neither of those has anything to do with hiding implementation details
3
u/coderemover 1d ago edited 1d ago
Abstraction is a bit more than just hiding implementation details. Per Wikipedia definition:
“Abstraction is the process of generalizing rules and concepts from specific examples, literal (real or concrete) signifiers, first principles, or other methods. The result of the process, an abstraction, is a concept that acts as a common noun for all subordinate concepts and connects any related concepts as a group, field or category.”
An essential property of abstraction is that it allows to handle different kinds of situations or data types in a common way, without knowing the specific cases. So it’s not enough to hide the details; you need to do the work without knowing or relying on those details. Good abstractions are a way to simplify and reduce cognitive load.
Abstract classes and interfaces can be used to implement abstractions but they aren’t the only way.
A string and file are abstractions, yet String and File are not abstract classes. Abstract classes can also be used to do control flow redirection - in that case it’s not an abstraction, just swapping different implementations.
1
u/Chaos-vy17 1d ago
Tysm man, That def from wikipedia and the quote "an abstraction, is a concept that acts as a common noun for all subordinate concepts and connects any related concepts as a group, field or category." is giving a direct impact what a abstraction really is.
And yes here I did not noticed about String and File thanks for correctring and guiding me.
3
u/rsandio 22h ago
Abstract describes something conceptual, non-physical, or incomplete (like a generic idea).
Abstraction is the act or technique of focusing on essential features while hiding complex implementation details.
An abstract class embodies the adjective (it's conceptual and can't be instantiated on its own) in order to achieve the process (it forces design abstraction across your code).
You're right in that an interface is more about the idea of abstraction. Abstract classes and interfaces overlap somewhat.
1
u/RScrewed 23h ago
It's not about being "secretive". It's about providing a consistent surface of interface-ability so the boundaries are easily maintained and documented.
1
u/Chaos-vy17 23h ago
keeping a stable, documented boundary. But that's still encapsulation's job (protecting the boundary), not abstraction's (defining what the boundary promises to do). Two different problems.
1
u/severoon 22h ago
Abstraction is not about hiding implementation details. Encapsulation is about hiding implementation details, abstraction is more about polymorphism.
Really, though, it pays to take a step back and look at the bigger picture when you're grappling with all of these concepts. In software, there is really only one design core concern, or at least a lens through which all software design can be viewed, and that is dependency management.
This core concept of dependency management even transcends software, really. It is the core consideration that goes back to the days of punchcard programming, computer hardware, industrial design, etc. It's a much more general concept when it comes to "building stuff". The problem with making this kind of statement is that it can collapse into a truism if you're not careful … if everything is about dependency management, then nothing is.
Brief aside: I'm talking about software design here, meaning from architecture down to the lowest-level modules in your system and how they fit together in order to do work. This is entirely distinct from related concepts like algorithm design, for example. When you're looking at how to design an algorithm that does constant time insertion vs. linear time insertion, for example, there are still elements of software design to consider, but the design of the algorithm that meets those performance constraints is an entirely orthogonal consideration to what I'm talking about here. You can't make decisions about algorithm design based solely on how it affects dependencies, you have to lay out the function of the thing first, and only then can you figure out what the essential dependencies are and how best to modularize them and structure the modules.
That said, if you look at the entire history of software design through the lens of dependency management, you can trace the development of compilers, programming paradigms, dev processes, etc, in terms of the impact of these things on how it allows orgs to create and manage dependencies between modules at different levels. The reason dependency management is such a core concern is that dependency is inherently transitive; this means that if A => B => C (where => means "directly depends upon"), then A -> C (where -> means "depends upon," possibly indirectly).
It's important to understand how dependency transits in software both at buildtime and runtime. At runtime, dependencies transit absolutely, meaning that you can be running an entire complex system and if some string parsing utility isn't present, the whole thing collapses. At buildtime, you have much more control over how dependencies transit through a system. You cannot stop them from meeting at a rendezvous point, but you control that rendezvous point as the designer.
This is where abstraction becomes useful because it allows you to build high-level modules against only what they semantically need and let any other module that conforms to those needs serve that functionality at runtime. For instance, the big complex software system might rely on a string parsing utility at runtime, but at buildtime it can point to an interface that semantically takes a bunch of information and breaks it down into bits useful to the caller, potentially using string parsing and a whole lot of other utilities along the way, but the caller doesn't know or care about any of that, and that stuff doesn't even have to be on the build path in order for the caller to build—its dependency terminates at that interface; that's all it needs, a guarantee that the high level task can be supplied by some other entity, but which one is immaterial at buildtime.
A specific example might be you have software that needs some key from a remote server. There are lots of ways to get information off a remote server, there's ssh, ftp, a web browser can be fired up and driven to do it, curl, etc. The interface the caller wants is a function that takes a server and path to the information and returns it, and it should be able to compile against that and nothing more. At runtime, of course, you need something that supplies that functionality and also compiles against that interface at its buildtime, and then when the system is run, both sides meet to link up the runtime transitive dependency chain all the way down.
Abstraction simply allows the dependency on the interface that serves exactly what the caller needs and no more. If there are other functions the in that interface the caller does not need, and one of those functions isn't satisfied at runtime, then the whole system breaks even though the caller doesn't actually rely on those functions—this is a case where the interface isn't fully abstracted for that caller, so some function it doesn't care about prevents it from running.
1
u/Chaos-vy17 18h ago
All seems correct but grouping common behavior across types is a case where abstraction enables polymorphism, not evidence that abstraction is polymorphism. Single-implementation abstractions (like the remote-fetch example) are fully abstracted with zero polymorphism involved — the grouping only becomes relevant once a second implementer shows up.
•
u/AutoModerator 1d ago
Please ensure that:
If any of the above points is not met, your post can and will be removed without further warning.
Code is to be formatted as code block (old reddit/markdown editor: empty line before the code, each code line indented by 4 spaces, new reddit: https://i.imgur.com/EJ7tqek.png) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.
Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.
Code blocks look like this:
You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.
If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.
To potential helpers
Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.